{"version":3,"sources":["app/assets/images/default-project-image.png","app/assets/icons/error.svg","app/assets/icons/exclamation.svg","app/assets/icons/stop.svg","app/assets/icons/snowflake.svg","internationalization/translations/en-US sync nonrecursive //.json$/i","internationalization/translations/fr-CA sync nonrecursive //.json$/i","hooks/observables/useObservable.tsx","app/common-page-components/general-contexts/BTGeneralContext.tsx","classes/commands/CommandBase.ts","classes/commands/sample-data/update-can-load-sample-data.ts","constants/general/index.ts","constants/routes/admin-routes.ts","classes/odata/bid-package-line-item-definition.ts","classes/odata/trade-requirement-definition.ts","classes/odata/bid-package-definitions.ts","constants/system-values/index.ts","utils/uuid.ts","services/odata/bt-odata-service.ts","constants/users/user-roles.ts","app/auth/user.ts","constants/users/index.ts","utils/config.ts","services/command/command-http-service.ts","services/login/login-service.ts","classes/odata/user.ts","services/query/query-http-service.ts","services/users/user-service.ts","services/authentication/authentication-service.ts","extensions/axiosMiddleware.ts","services/odata/odata-http-service.ts","services/bid-package-maintenance/bid-package-maintenance-service.ts","app/enums/bid-package-enums.ts","classes/odata/bidder.ts","utils/general.ts","utils/math.ts","utils/strings.ts","classes/odata/adjustment.ts","classes/odata/bid-package-bid-classification-total.ts","classes/odata/bid-package-bid-total.ts","classes/odata/bid-package-line-item-bid.ts","classes/odata/bid-package-line-item-metadata.ts","classes/odata/bid-package-line-item-order.ts","classes/odata/bid-package-line-item.ts","classes/odata/bid-package-line-item-rollup-bid.ts","classes/odata/bid-package-line-items-total.ts","classes/odata/bid-package-line-item-group-order.ts","classes/odata/bid-package-requirement-fulfillment.ts","classes/odata/bid-package-requirement.ts","app/enums/fee-enum.ts","classes/odata/bid-package.ts","classes/odata/bid-package-contingency-amount.ts","classes/odata/bidder-file-upload.ts","services/bid-packages/bid-package-service.ts","classes/odata/alternate.ts","services/bid-summary/bid-summary-service.ts","classes/odata/fee-definition.ts","services/fees/fee-service.ts","classes/odata/frozen-entity.ts","services/frozen-entities/frozen-entities-service.ts","classes/odata/general-requirement-definition.ts","services/general-requirements/general-requirements-service.ts","classes/odata/preferences.ts","constants/preferences/measurement-systems.ts","constants/preferences/index.ts","services/preferences/preferences-service.ts","classes/odata/fee-calculated-values.ts","app/common-page-components/notification-panel/NotificationPanelContext.tsx","classes/odata/fee.ts","classes/odata/project.ts","services/projects/project-service.ts","services/recent-projects/recent-projects-service.ts","classes/odata/project-view-setting.ts","classes/odata/all-project-view-setting.ts","services/settings/settings-service.ts","classes/odata/system-value.ts","services/system-values/system-values-service.ts","classes/odata/unit-of-measure.ts","services/units-of-measure/units-of-measure-service.ts","classes/commands/CommandBatchBase.ts","services/command/command-manager-service.ts","services/logger/Logger.tsx","app/common-page-components/floating-loading-indicator/FloatingLoadingIndicatorContext.tsx","app/common-page-components/loading-page-overlay/LoadingPageOverlayContext.tsx","app/shared-page-components/hooks/useCommandServiceHelper.tsx","app/common-page-components/confirmation-overlay/ConfirmationOverlayContext.tsx","app/shared-page-components/hooks/useSampleDataDialog.tsx","constants/routes/error-routes.ts","constants/routes/settings-routes.ts","constants/routes/index.ts","app/common-page-components/navigation-menu/NavigationMenu.tsx","app/common-page-components/layout/Layout.tsx","app/common-page-components/routes/AuthenticatedRoute.tsx","app/common-page-components/routes/guards/ProjectGuard.tsx","app/common-page-components/support-overlay/SupportOverlayContext.tsx","app/common-page-components/controls/button/BTButton.tsx","app/common-page-components/page-header/PageHeader.tsx","app/common-page-components/svg-image/SvgImage.tsx","app/pages/admin/frozen-entities/FrozenEntitiesAdminPage.tsx","app/pages/common/error/generic-error/GenericErrorPage.tsx","app/pages/common/error/page-not-found/PageNotFoundPage.tsx","app/pages/common/error/unauthorized/UnauthorizedPage.tsx","app/pages/common/error/unlicensed/UnlicensedPage.tsx","services/notification/notification-service.ts","app/pages/common/home/HomePage.tsx","app/common-page-components/cards-container/BTCardsContainer.tsx","app/common-page-components/controls/floating-icon-button/BTFloatingIconButton.tsx","app/common-page-components/filter-tree/BTFilterTreeRow.tsx","app/common-page-components/forms/FormFooter.tsx","app/common-page-components/inputs/BTDropDownList.tsx","app/common-page-components/inputs/BTRadioGroup.tsx","app/common-page-components/modal/BTModalContext.tsx","app/common-page-components/modal/BTModal.tsx","app/common-page-components/filter-tree/BTFilterTreeSettingsModal.tsx","app/common-page-components/filter-tree/BTFilterTree.tsx","app/common-page-components/frozen-entity-notification/FrozenEntityNotification.tsx","app/common-page-components/tabs/BTTabsContainer.tsx","utils/dates.ts","utils/ee.ts","app/common-page-components/controls/icon-button/BTIconButton.tsx","app/common-page-components/card/BTCard.tsx","app/common-page-components/controls/icon-button-toggle/BTIconButtonToggle.tsx","app/pages/common/home/components/ProjectSearchResultCard.tsx","constants/links/index.ts","app/pages/common/login/LoginPage.tsx","classes/commands/bid-package-maintenance/bid-package-definitions/create-bid-package-definition-command.ts","classes/commands/bid-package-maintenance/bid-package-definitions/delete-bid-package-definition-command.ts","classes/commands/bid-package-maintenance/bid-package-definitions/update-bid-package-definition-code-command.ts","classes/commands/bid-package-maintenance/bid-package-definitions/update-bid-package-definition-description-command.ts","classes/commands/bid-package-maintenance/trade-requirement-definitions/create-trade-requirement-definition-command.ts","classes/commands/bid-package-maintenance/trade-requirement-definitions/update-trade-requirement-definition-description-command.ts","classes/commands/bid-package-maintenance/trade-requirement-definitions/update-trade-requirement-definition-index-command.ts","classes/commands/bid-package-maintenance/trade-requirement-definitions/update-trade-requirement-definition-requirement-fulfillment-type-command.ts","classes/commands/bid-package-maintenance/trade-requirement-definitions/delete-trade-requirement-definition-command.ts","classes/commands/bid-package-maintenance/batch-commands/bid-package-maintenance-batch-commands.ts","services/dispatch-manager/DispatchManager.tsx","app/feature-flagging/features.ts","hooks/dispatch-manager-helper/useDispatcherWithCommandManagerService.tsx","services/command/reducers/command-manager-batch-command-initializer-reducer.ts","services/command/reducers/command-manager-dispatch-reducer.ts","utils/command-manager-service.ts","app/common-page-components/search/BTSearchBar.tsx","app/shared-page-components/hooks/useDegradedActionNotifications.tsx","app/common-page-components/sortable/BTSortableContainer.tsx","constants/general/entity-validation-constants.ts","app/common-page-components/inputs/BTInput.tsx","app/pages/settings/bid-packages/components/TradeRequirementsListing.tsx","app/pages/settings/bid-packages/components/BidPackageDefinitionListing.tsx","app/pages/settings/bid-packages/components/BidPackageDefinitionListingContainer.tsx","utils/forms.ts","app/common-page-components/forms/form-error-container/FormErrorContainer.tsx","app/common-page-components/forms/hooks/useFocusOnRender.tsx","app/common-page-components/forms/FormTextInput.tsx","app/pages/settings/bid-packages/components/BidPackageEditForm.tsx","app/pages/settings/bid-packages/reducers/bid-package-maintenance-reducer.ts","app/pages/settings/bid-packages/BidPackageMaintenancePage.tsx","classes/commands/fee-maintenace/commands/update-fee-definition-amount-command.ts","classes/commands/fee-maintenace/commands/update-fee-definition-order-command.ts","classes/commands/fee-maintenace/commands/update-fee-definition-name-command.ts","classes/commands/fee-maintenace/commands/update-fee-definition-type-command.ts","classes/commands/fee-maintenace/commands/create-fee-definition-command.ts","classes/commands/fee-maintenace/commands/delete-fee-definition-command.ts","classes/commands/fee-maintenace/batch-commands/fee-maintenace-batch-commands.ts","utils/feeLabel.ts","app/common-page-components/inputs/BTNumericInput.tsx","app/common-page-components/fee-table/components/FeeTableItem.tsx","app/common-page-components/fee-table/FeeTable.tsx","app/pages/settings/fees/reducers/fees.ts","app/pages/settings/fees/FeesPage.tsx","classes/commands/general-conditions/general-conditions-definitions/create-general-conditions-bid-package-definition-command.ts","classes/commands/general-conditions/general-conditions-definitions/update-general-conditions-bid-package-definition-code-command.ts","classes/commands/general-conditions/general-conditions-definitions/update-general-conditions-bid-package-definition-description.ts","classes/commands/general-conditions/line-item-definitions/create-bid-package-line-item-definition-command.ts","classes/commands/general-conditions/line-item-definitions/delete-bid-package-line-item-definition-command.ts","classes/commands/general-conditions/line-item-definitions/update-bid-package-line-item-definition-description-command.ts","classes/commands/general-conditions/line-item-definitions/update-bid-package-line-item-definition-index-command.ts","classes/commands/general-conditions/line-item-definitions/update-bid-package-line-item-definition-unit-of-measure-command.ts","classes/commands/general-conditions/batch-commands/general-conditions-batch-command.ts","app/pages/settings/general-conditions/components/GeneralConditionsEditForm.tsx","app/pages/settings/general-conditions/components/LineItemListItem.tsx","app/pages/settings/general-conditions/hooks/useGeneralConditionContainer.tsx","app/pages/settings/general-conditions/reducers/general-conditions-reducer.ts","app/pages/settings/general-conditions/GeneralConditionsPage.tsx","classes/commands/general-requirements/general-requirements-definitions/create-general-requirement-definition-command.ts","classes/commands/general-requirements/general-requirements-definitions/delete-general-requirement-definition-command.ts","classes/commands/general-requirements/general-requirements-definitions/update-general-requirement-definition-description-command.ts","classes/commands/general-requirements/general-requirements-definitions/update-general-requirement-definition-index-command.ts","classes/commands/general-requirements/general-requirements-definitions/update-general-requirement-definition-requirement-fulfillment-type-command.ts","classes/commands/general-requirements/batch-commands/general-requirements-batch-commands.ts","constants/requirements/index.ts","app/pages/settings/general-requirements/components/RequirementListItem.tsx","app/pages/settings/general-requirements/hooks/useRequirementList.tsx","app/pages/settings/general-requirements/reducers/general-requirement-reducer.ts","app/pages/settings/general-requirements/GeneralRequirementsPage.tsx","classes/commands/preferences/update-measurement-system-command.ts","classes/commands/preferences/update-bidders-ranges-command.ts","classes/commands/preferences/batch-commands/preferences-batch-command.ts","app/common-page-components/forms/FormNumericTextInput.tsx","app/pages/settings/preferences/components/PreferencesEditForm.tsx","app/pages/settings/preferences/reducers/preferences-reducer.ts","app/pages/settings/preferences/PreferencesPage.tsx","app/pages/settings/units-of-measure/components/UnitOfMeasureForm.tsx","app/pages/settings/units-of-measure/components/UnitOfMeasureListing.tsx","app/pages/settings/units-of-measure/UnitsOfMeasurePage.tsx","app/pages/settings/user-permissions/components/LocationListing.tsx","app/common-page-components/forms/FormComboBox.tsx","app/common-page-components/forms/FormMultiSelect.tsx","app/pages/settings/user-permissions/components/UserEditForm.tsx","app/pages/settings/user-permissions/components/UserListing.tsx","app/pages/settings/user-permissions/UserPermissionsPage.tsx","classes/commands/bid-packages/clear-selected-bidder-on-bid-package-command.ts","classes/commands/bid-packages/delete-bid-package-bidder-command.ts","classes/commands/bid-packages/delete-bid-package-line-item-command.ts","classes/commands/bid-packages/delete-bidder-requirement-fulfillment-on-bid-package-command.ts","classes/commands/bid-packages/delete-line-item-bid-on-bid-package-command.ts","classes/commands/bid-packages/set-bidder-order-command.ts","classes/commands/bid-packages/set-bidder-status-command.ts","classes/commands/bid-packages/set-selected-bidder-on-bid-package-command.ts","classes/commands/bid-packages/update-bid-package-line-item-order-command.ts","classes/commands/bid-packages/update-bid-package-line-item-group-order-command.ts","constants/bid-package/index.ts","app/common-page-components/grid/grid-container/BTGridContainerContext.tsx","app/feature-flagging/FeatureFlagContext.tsx","app/shared-page-components/ProjectInfoModal.tsx","app/shared-page-components/hooks/useProject_Info.tsx","app/common-page-components/grid/BTGridDraggedElement.tsx","utils/dom.ts","app/common-page-components/context-menu/BTContextMenuContext.tsx","app/common-page-components/context-menu/BTContextMenu.tsx","app/common-page-components/grid/grid-row/BTGridRowCell.tsx","app/common-page-components/grid/grid-row/BTGridRow.tsx","app/common-page-components/grid/sub-grid/BTSubGrid.tsx","app/common-page-components/grid/grid-container/BTGridContainerGridSection.tsx","app/common-page-components/grid/grid-container/hooks/useBTGridContainerKeyboardNavigation.tsx","app/common-page-components/grid/grid-container/BTGridContainer.tsx","app/pages/specific/bid-package/BidPackagePageContext.tsx","classes/commands/bid-packages/add-line-item-to-bid-package-command.ts","classes/commands/bid-packages/update-bid-package-line-item-command.ts","app/common-page-components/items-manager-grid/cells/BTItemsManagerGridAutoCompleteCell.tsx","app/common-page-components/items-manager-grid/cells/BTItemsManagerGridDropdownCell.tsx","app/common-page-components/items-manager-grid/cells/BTItemsManagerGridNumericCell.tsx","app/common-page-components/items-manager-grid/cells/BTItemsManagerGridTextCell.tsx","app/pages/specific/bid-package/components/AddEditLineItemsForm.tsx","app/common-page-components/keyboard-shortcuts-info/KeyboardShortcutsInformation.tsx","app/pages/specific/bid-package/components/BidPackageKeyboardShortcuts.tsx","app/common-page-components/alert/BTAlert.tsx","app/common-page-components/notification-service-status-message/NotificationServiceStatusMessage.tsx","app/pages/specific/bid-package/components/BidPackagePageHeader.tsx","classes/commands/bid-packages/delete-adjustment-on-bid-package-command.ts","classes/commands/bid-packages/set-adjustment-on-bid-package-command.ts","app/pages/specific/bid-package/hooks/bid-handlers/useBidPackageBidHandler_Adjustments.tsx","classes/commands/bid-packages/set-line-item-bid-on-bid-package-command.ts","app/pages/specific/bid-package/hooks/bid-handlers/useBidPackageBidHandler_LineItemBids.tsx","classes/commands/bid-packages/delete-line-item-rollup-bid-on-bid-package-command.ts","classes/commands/bid-packages/set-line-item-rollup-bid-on-bid-package-command.ts","app/pages/specific/bid-package/hooks/bid-handlers/useBidPackageBidHandler_LineItemRollupBids.tsx","classes/commands/bid-packages/set-bidder-requirement-fulfillment-on-bid-package-command.ts","app/pages/specific/bid-package/hooks/bid-handlers/useBidPackageBidHandler_RequirementFulfillments.tsx","classes/commands/bid-packages/add-edit-bid-package-notes-to-bid-package-command.ts","app/common-page-components/forms/FormTextAreaInput.tsx","app/common-page-components/notes/BTNotes.tsx","classes/commands/bid-packages/update-bid-package-lock-command.ts","app/pages/specific/bid-package/hooks/useBidPackage.tsx","classes/commands/bid-packages/add-edit-adjustment-notes-to-bid-package-command.ts","app/pages/specific/bid-package/hooks/useBidPackageAdjustments_Notes.tsx","classes/commands/bid-packages/add-bidder-to-bid-package-command.ts","classes/commands/bid-packages/update-bid-package-bidder-command.ts","app/pages/specific/bid-package/components/AddEditBiddersForm.tsx","app/pages/specific/bid-package/hooks/useBidPackageBidders_AddEditForm.tsx","classes/commands/bid-packages/delete-bid-package-bidder-document-command.ts","app/common-page-components/upload/BTUpload.tsx","app/pages/specific/bid-package/components/BidderDocumentsForm.tsx","app/pages/specific/bid-package/components/BidderDocumentsModal.tsx","app/pages/specific/bid-package/hooks/useBidPackageBidders_DocumentsModal.tsx","app/pages/specific/bid-package/components/BidderInfoModal.tsx","app/pages/specific/bid-package/hooks/useBidPackageBidders_InfoModal.tsx","classes/commands/bid-packages/add-edit-bidder-notes-to-bid-package-command.ts","app/pages/specific/bid-package/hooks/useBidPackageBidders_Notes.tsx","utils/btgrid.tsx","app/common-page-components/popover/BTPopoverContext.tsx","app/pages/specific/bid-package/hooks/helpers/useBidderHelpers.tsx","app/pages/specific/bid-package/hooks/useBidPackageGrid_Adjustments.tsx","app/pages/specific/bid-package/hooks/useBidPackageGrid_Header.tsx","app/pages/specific/helper-hooks/useHelperHook.tsx","app/pages/specific/bid-package/hooks/helpers/useLineItemsHelpers.tsx","app/pages/specific/bid-package/hooks/useBidPackageGrid_LineItems.tsx","app/pages/specific/bid-package/hooks/useBidPackageGrid_LineItems_Alternates.tsx","app/pages/specific/bid-package/components/BidderStatusDropdown.tsx","app/pages/specific/bid-package/components/BidderTrophyIcon.tsx","app/pages/specific/bid-package/hooks/useBidPackageGrid_LineItems_Header.tsx","app/pages/specific/bid-package/hooks/useBidPackageGrid_Requirements.tsx","app/pages/specific/bid-package/hooks/useBidPackage_ChangeNotifications.tsx","app/pages/specific/bid-package/hooks/useBidPackage_LineItems.tsx","app/pages/specific/bid-package/hooks/useProject_ChangeNotifications.tsx","app/pages/specific/bid-package/BidPackagePage.tsx","classes/commands/project/add-edit-project-notes-to-project-command.ts","classes/commands/project/close-project-command.ts","classes/commands/project/fees/add-project-fee-command.ts","classes/commands/project/fees/delete-project-fee-command.ts","classes/commands/project/fees/update-project-fee-command.ts","classes/commands/project/fees/update-project-fee-order-command.ts","classes/commands/project/fees/project-fees-batch-command.ts","app/pages/specific/bid-summary/BidSummaryPageContext.tsx","app/pages/specific/bid-summary/components/BidSummaryKeyboardShortcuts.tsx","app/pages/specific/bid-summary/hooks/fees/useFeeTable.tsx","classes/commands/project/update-project-bidders-ranges-command.ts","app/pages/specific/bid-summary/components/ProjectBiddersRangesEditForm.tsx","app/pages/specific/bid-summary/hooks/settings/useBidSummary_Settings_ProjectBiddersRangesModal.tsx","classes/commands/bid-packages/set-contingency-command-on-bid-package.ts","app/pages/specific/bid-summary/hooks/useBidSummary.tsx","app/common-page-components/inputs/BTSwitch.tsx","app/pages/specific/bid-summary/hooks/bid-package/useBidSummary_BidPackage_Alternate.tsx","app/pages/specific/bid-summary/hooks/bid-package/useBidSummary_BidPackage_BidAmount.tsx","app/pages/specific/bid-summary/hooks/bid-package/useBidSummary_BidPackage_BidPackages.tsx","app/pages/specific/bid-summary/hooks/bid-package/useBidSummary_BidPackage_Classification.tsx","app/pages/specific/bid-summary/hooks/bid-package/useBidSummary_BidPackage_ComparisonToBaseEstimate.tsx","app/pages/specific/bid-summary/hooks/bid-package/useBidSummary_BidPackage_Contingencies.tsx","app/pages/specific/bid-summary/hooks/bid-package/useBidSummary_BidPackage_Notes.tsx","app/pages/specific/bid-summary/hooks/bid-package/useBidSummary_BidPackage_SecondBidderAnalysis.tsx","app/pages/specific/bid-summary/hooks/bid-package/useBidSummary_BidPackage_Totals.tsx","app/pages/specific/bid-summary/hooks/fees/useBidSummary_Fees_Alternate.tsx","app/pages/specific/bid-summary/hooks/fees/useBidSummary_Fees_Alternate_Placeholder.tsx","app/pages/specific/bid-summary/hooks/fees/useBidSummary_Fees_BidAmount.tsx","app/pages/specific/bid-summary/hooks/fees/useBidSummary_Fees_Classifications.tsx","app/pages/specific/bid-summary/hooks/fees/useBidSummary_Fees_Contingencies.tsx","app/pages/specific/bid-summary/components/FeeCalculationFailureNotification.tsx","app/pages/specific/bid-summary/hooks/fees/useBidSummary_Fees_Fees.tsx","app/pages/specific/bid-summary/hooks/fees/useBidSummary_Fees_Totals.tsx","app/pages/specific/bid-summary/hooks/useBidSummaryGrid.tsx","app/pages/specific/bid-summary/hooks/useBidSummaryPageHeader.tsx","classes/commands/project/update-project-alternate-enabled-state-command.ts","app/pages/specific/bid-summary/hooks/useBidSummary_Alternates.tsx","app/pages/specific/bid-summary/hooks/useBidSummary_ChangeNotifications.tsx","app/pages/specific/bid-summary/BidSummaryPage.tsx","classes/commands/project/create-project-command.ts","classes/commands/project/update-project-command.ts","utils/navigation-helpers.ts","app/pages/specific/project/components/ProjectErrorDisplay.tsx","app/pages/specific/project/components/AddEditAlternates.tsx","app/common-page-components/inputs/BTCheckBox.tsx","app/pages/specific/project/components/AddEditBidPackages.tsx","app/pages/specific/project/components/AddEditFees.tsx","app/pages/specific/project/components/AddEditGeneralRequirements.tsx","app/common-page-components/inputs/BTMultiSelect.tsx","app/pages/specific/project/components/AddEditPermissions.tsx","app/common-page-components/inputs/BTDatePicker.tsx","app/pages/specific/project/components/AddEditProjectInformation.tsx","app/pages/specific/project/reducers/add-edit-project-reducer.ts","app/pages/specific/project/ProjectPage.tsx","utils/imports.ts","internationalization/i18n.ts","utils/hooks/useVersionCheck.tsx","utils/hooks/useScript.tsx","utils/hooks/useWalkMe.tsx","App.tsx","utils/font-awesome.ts","app/common-page-components/confirmation-overlay/ConfirmationOverlay.tsx","app/common-page-components/ee/balloons/EEBalloons.tsx","app/common-page-components/floating-loading-indicator/FloatingLoadingIndicator.tsx","app/common-page-components/loading-indicator/LoadingIndicator.tsx","app/common-page-components/loading-page-overlay/LoadingPageOverlay.tsx","app/common-page-components/mobile-device-overlay/MobileDeviceOverlay.tsx","app/common-page-components/notification-panel/NotificationPanel.tsx","app/common-page-components/popover/BTPopover.tsx","app/common-page-components/reload-app-timer/ReloadAppTimer.tsx","app/common-page-components/support-overlay/SupportOverlay.tsx","internationalization/setup.ts","registerServiceWorker.ts","index.tsx","services/logger/AppInsights.ts"],"names":["module","exports","map","webpackContext","req","id","webpackContextResolve","__webpack_require__","o","e","Error","code","keys","Object","resolve","useObservable","_subject","useRef","Subject","observable$","current","asObservable","updateObservableValue","useCallback","next","useObservableWithValue","newValue","useObservableWithBehaviorSubject","initialValue","_behaviorSubject","BehaviorSubject","BTGeneralContext","React","createContext","BTGeneralContextProvider","props","useState","systemSettings","setSystemSettings","userJustGotTheLatestUpdate$","onUserJustGotTheLatestUpdate","appWillRestart$","onAppWillRestart","signalRResponseTimeout","pageScroll_X$","setPageScroll_X","pageScroll_Y$","setPageScroll_Y","windowResize$","setWindowResize","easterEgg_BoogieNights","setEasterEgg_BoogieNights","Provider","value","children","CommandBase","type","apiUrl","httpMethod","__type","this","propertiesToIgnore","returnValue","thisAsAny","getOwnPropertyNames","filter","v","includes","forEach","currKey","UpdateCanLoadSampleDataCommand","GeneralConstants","ENTITY_IDS","SYSTEM_SETTINGS","BID_DAY_APPLICATION","PRODUCT_NAME","PRODUCT_NAME_FULL","KEY_A","KEY_B","KEY_C","KEY_G","KEY_I","KEY_M","KEY_N","KEY_O","KEY_R","KEY_S","KEY_V","KEY_X","KEY_Z","KEY_ARROW_DOWN","KEY_ARROW_LEFT","KEY_ARROW_RIGHT","KEY_ARROW_UP","KEY_BACKSPACE","KEY_DELETE","KEY_ENTER","KEY_ESCAPE","KEY_HYPHEN","KEY_PERIOD","KEY_SPACE","KEY_TAB","ROUNDING_MODE","TRUNCATE","ROUND_HALF_UP","DECIMAL_PRECISION_FORMAT","MINIMUM_FRACTION_DIGITS","MAXIMUM_FRACTION_DIGITS","EMPTY_FULL_PRECISION","PERCENT_MINIMUM_FRACTION_DIGITS","PERCENT_MAXIMUM_FRACTION_DIGITS","SIGNALR_WAIT_TIMEOUT","UI_ZINDEXBASE","AdminRoutes","FROZEN_ENTITIES","join","BidPackageLineItemDefinition","oDataResourceName","bidPackageDefinitionId","index","description","unitOfMeasure","TradeRequirementDefinition","requirementFulfillmentType","bidPackageCode","BidPackageDefinition","Type","SystemValues","DOMAINS","GENERAL_CONDITIONS_CODE","CAN_LOAD_SAMPLE_DATA","generateUuid","replace","c","crypto","getRandomValues","Uint8Array","toString","isValidUuid","uuid","RegExp","test","emptyUuid","BTODataService","query","propertyName","expandedODataUrlParts","filtersStringParts","selectorsStringParts","useCount","top","filters","length","currFilter","generateFilterStringPart","queryFilter","oDataOperatorString","getODataFilterOperator","valueIsUuid","Date","moment","toISOString","valueAsQuery","push","selectors","currSelectorPropertyName","expandedQueries","currQuery","generateODataUrlPart","odataUrlPart","filtersString","selectorsString","expandString","currUrlPart","generateODataUrlStringFragments","countString","topString","atRootLevel","concatenationCharacter","stringsToCombine","oDataClass","oDataUrlParts","oDataUrlString","ODataQueryBuilder","rootQuery","currentQuery","filterType","filterValue","propertyNames","existingQuery","find","newExpandedQuery","topValue","UserRolesValues","UserRolesDisplayNames","UserInformation","email","name","location","roles","licensed","isLicensed","json","assign","isUserAuthorized","userRole","undefined","UserRoles","Contributor","ProjectAdmin","Admin","BidDaySupport","Dev","getConfig","key","env","window","ENV","configVal","process","CommandHttpService","getAuthHeaders","authHeaders","service","axios","create","baseURL","commandApiUrl","headers","axiosMiddleware","setMiddleware","AuthenticationService","getAccessToken","commandApiScope","accessToken","Authorization","AppAuth","getAuthToken","loginUser","targetClientOrgId","a","getCommandHttpService","post","response","data","getClientOrganizations","get","User","QueryHttpService","queryApiScope","queryApiUrl","SSOPasswordResetStatus","SSOErrorCode","userFromData","isNew","toLowerCase","role","getAllUsers","oDataQuery","UserData","getQueryObject","ODataHttpService","toArray","userData","users","getUserById","firstOrDefault","result","getUserByEmail","getQueryService","addUser","user","dto","r","deleteUser","delete","params","editUser","put","getCurrentUser","localStorage","msalObj","getAccount","currentUserInfo","authErrorMessage","loginErrorMessage","getItem","LoginApi","authToken","tokenParts","split","setItem","BidDayAuthToken","tokenPayload","JSON","parse","atob","some","loadUserInfo","error","isAxiosError","status","detail","account","setUnknownUserInfo","UserApi","from","genericErrorMessage","Msal","msalConfig","setAuthRedirectCallBack","clear","clearPasswordResetStatus","authority","signInAuthority","loginRedirect","requestObj","passwordResetAuthority","logout","scope","acquireTokenSilent","scopes","errorCode","hash","urlContainsHash","SSOError","removeItem","None","handleRedirectCallback","message","indexOf","Initiated","resetPassword","setSSOErrors","idTokenClaims","acr","Completed","errorDescription","OtherError","LicensingAppSSOError","trim","ssoError","stringify","userInfo","loginScopes","clientId","redirectUri","cacheLocation","concat","auth","validateAuthority","postLogoutRedirectUri","cache","storeAuthStateInCookie","system","loadFrameTimeout","axiosToConfigure","defaults","interceptors","request","use","config","url","oDataUrl","queryObj","getODataHttpService","httpService","generateODataUrlString","responseValue","plainToClass","odataCount","BidClassificationTypes","RequirementFulfillmentTypes","bidPackageDefinitionFromData","tradeRequirementDefinitions","t","lineItemDefinitions","l","getAllBidPackageDefinitions","SystemValuesApi","getSystemValue","generalConditionsCode","dataQueryBuilder","BidPackageDefinitionData","expand","definitions","d","getGeneralConditionsDefinition","BidderStatus","scrollToRef","ref","currentRef","newScrollPosition","offsetTop","Scroll","scrollTo","duration","convertBigToNumber","numberToConvert","decimalPlaces","enableRounding","round","toNumber","formatNumberAsCurrency","number","formatNumberAsCurrencyCustomPrecision","formatNumberAsCurrencyFull","Big","Intl","NumberFormat","style","currency","minimumFractionDigits","maximumFractionDigits","format","formatNumberAsPercentage","formatter","formatNumberAsDecimal","normalizeNullOrUndefined","getEnvironmentName","isEnvironment","environment","currEnvironment","sumBigNumbers","args","reduce","accumulator","currValue","add","isEmptyOrWhitespace","text","doesStringExistInOtherString","stringToCheck","searchString","caseSensitive","areTrimmedStringsEqual","original","compareTo","useLocale","trimmedOriginal","trimmedCompareTo","toLocaleLowerCase","getDuplicates","values","valuesWithoutDuplicates","Set","duplicates","item","i","slice","getEmailWithoutDomain","isValidEmail","isValidPhoneNumber","phoneNumber","matches","match","getSanitizedExcelRows","excelClipboardText","rows","row","cells","every","removeNonNumericCharsFromString","inputString","Adjustment","init","isDirty","bidPackageId","alternateId","bidderId","notes","notesId","adjustmentToMerge","BidPackageBidClassificationTotal","classification","amount","BidPackageBidTotal","bidsTotal","adjustmentAmount","BidPackageLineItemBid","bidPackageLineItemId","price","Included","MissingScope","BidPackageLineItemMetadata","BidPackageLineItemOrder","bidPackageLineItemGroupOrderId","order","BidPackageLineItem","baseEstimate","quantity","quantityUnitOfMeasure","unitPrice","getBaseEstimate","metadata","copy","findIndex","splice","times","BidPackageLineItemRollupBid","metadataValue1","metadataValue2","bidValue","BidPackageLineItemsTotal","total","BidPackageLineItemGroupOrder","classificationLevel1","classificationLevel2","BidPackageRequirementFulfillment","bidPackageRequirementId","BidPackageRequirement","requirementType","FeeTypes","Bidder","companyName","faxNumber","fileUploadContainerId","primaryContactEmail","primaryContactName","inEdit","originalCompanyName","DeclinedToQuote","QuoteIsLate","hasExcludedStatus","BidPackage","assignedToUser","assignedToUserId","contingencyAmount","contingencyPercentage","isGeneralCondition","lockedByUserEmail","project","projectId","selectedBidder","selectedBidderId","lineItemsTotals","getBaseBidAmountInfoForBidder","bidTotalForBidder","bidTotals","classificationTotals","bidClassificationTotals","lineItems","bids","m","Unallocated","lineItem","matchingBid","calculatedBidPrice","otherBids","sortBy","Risk","alternates","baseBidAmount","alternateBidsAmount","enabledAlternateIds","enabled","currAlternateId","amount1","amount2","eq","div","sub","mul","lineItemId","newLineItemBid","doNotSetLineItemBidIfDirty","lineItemToUpdateIndex","lineItemToUpdate","cloneDeep","lineItemBidToAddOrUpdate","clone","indexOfLineItemBidToUpdate","lineItemBidsCopy","lineItemsCopy","indexOfLineItemBidToDelete","lineItemRollupBids","newLineItemRollupBid","indexOfBidToUpdate","lineItemRollupBidToAddOrUpdate","lineItemRollupBidsCopy","indexOfBidToDelete","rollupBidsCopy","adjustments","newAdjustment","mergeNewAdjustment","matchingAdjustmentIndex","newAdjustmentToAddOrUpdate","adjustmentsCopy","mergeExistingAdjustment","existingLineItemIndex","lineItemToAddOrUpdate","lineItemGroupOrders","bidders","matchingBidder","b","orderBy","bidder","requirementId","requirements","isTradeRequirement","getTradeRequirements","getGeneralRequirements","requirement","getRequirement","requirementFulfillments","newRequirementFulfillment","requirementIndex","requirementToUpdate","indexOfRequirementFulfillmentToUpdate","newRequirementFulfillmentToAddOrUpdate","fulfillmentsCopy","requirementsCopy","newRequirementToAddOrUpdate","indexOfRequirementFulfillmentToDelete","allRollupBids","BidPackageContingencyAmount","BidderFileUpload","fileName","uploadDate","getBidPackages","select","getBidPackagesForProject","getBidPackageById","bidPackageResult","bidPackage","getBidPackageTotals","getBidPackageContingencyAmounts","bidPackageIds","contingencyAmounts","addLineItemsToBidPackage","commands","updateBidPackageLineItems","deleteBidPackageLineItems","addBiddersToBidPackage","updateBidPackageBidders","getBidderDocumentDownloadUrl","bidderCompanyName","getApiUrl","getBidderDocumentUploadUrl","getBidderFileUploadsByBidPackageIdAndCompanyName","bidderFileUploadResults","fileUploads","bfu","Alternate","getBidPackagesByProjectId","getAlternatesByProjectId","FeeDefinition","feeType","referenceFeeName","getFeeDefinitions","calculateFeesForProject","calculateFeesForGrid","calculateFeesDTO","FrozenEntity","entityType","entityId","dateFrozen","checkIfEntityIsFrozen","count","getCount","itemCount","getAllFrozenEntities","getFrozenEntitiesListings","syncEntity","unfreezeEntity","GeneralRequirementDefinition","getAllGeneralRequirementDefinitions","Preference","MeasurementSystemValues","MeasurementSystemDisplayNames","MeasurementSystems","preferencesFromData","newPreferences","measurementSystem","lowBiddersMax","midBiddersMax","obj","prefProp","propName","Number","x","isNaN","getPreferences","PreferenceData","preferenceArrayData","preferences","NotificationPanelTypes","FeeCalculatedValues","calculatedContingencyValue","calculatedValue","feeId","Fee","currFee","allFees","counter","Percent","matchingFee","getLastReferencedFeeForPercentFee","Project","architect","bidDueDate","dateCreated","completionDate","contributors","imageUri","isHardBid","isClosed","lineItemRollup1","lineItemRollup2","owner","projectAdmins","siteAddress","startDate","subtitle","totalBuildingArea","totalBuildingAreaUnitOfMeasure","totalSiteArea","totalSiteAreaUnitOfMeasure","hasFeeCalculationFailure","parts","streetAddress","aptSuiteBldg","city","stateOrRegion","postalCode","bidPackages","baseEstimateAmount","bp","bpTotal","getBaseEstimateAmount","alternate","calculateBaseEstimateAmount","calculateAlternateAmountForAllBidPackages","calculateContingencyAmountForAllBidPackages","commandServiceUrl","getProjectInfoById","getFeesByProjectId","getAllProjectInfos","currentProjectInfo","getProjectCount","getFeesAndTotalsByProjectId","getProjectInfoForBidPackage","getLineItemMetadataForProject","getProjectImageBlobUrl","responseType","blobUrl","URL","createObjectURL","encodeURIComponent","searchAllProjects","dateRange","searchText","searchResults","currentResult","exportProjectToExcel","filename","disposition","exec","FileSaver","saveAs","getProjectImageUploadUrl","getRecentProjectsForUser","addRecentProject","recentProject","ProjectViewSetting","groupingKey1","groupingKey2","userId","AllProjectViewSetting","getProjectViewSettings_Recent","getProjectViewSettings_All","updateProjectViewSettings","settings","SystemValue","systemValueName","SystemValueData","systemValueData","UnitOfMeasure","getAllUnitsOfMeasure","addUnitOfMeasure","deleteUnitOfMeasure","unitOfMeasureName","CommandBatchBase","allowedCommandClassTypes","allCommands","validateCommandTypes","commandObj","generateRequestData","commandObjects","currCommandObj","constructor","CommandManagerService","commandToExecute","shift","executeCommand","requestData","Logger","appInsightsPlugin","log","debug","warn","trackException","exception","severityLevel","SeverityLevel","LoggingContext","useLogger","useContext","LoggingContextProvider","logger","FloatingLoadingIndicatorContext","FloatingLoadingIndicatorContextProvider","previousValue_DisplayInfo_Blue","previousValue_DisplayInfo_Green","displayInfo_Blue$","setDisplayInfo_Blue","displayInfo_Green$","setDisplayInfo_Green","showFloatingLoadingIndicator_Blue","hideFloatingLoadingIndicator_Blue","showFloatingLoadingIndicator_Green","hideFloatingLoadingIndicator_Green","floatingLoadingIndicatorDisplayInfo_Blue$","floatingLoadingIndicatorDisplayInfo_Green$","LoadingPageOverlayContext","LoadingPageOverlayContextProvider","currCounterValue","loadingOverlayCounter$","setLoadingOverlayCounter","showPageLoadingOverlay","hidePageLoadingOverlay","forceHide","Math","max","NotificationPanelContext","NotificationPanelContextProvider","queuedNotificationsCurrValue","queuedNotifications$","setQueuedNotifications","useEffect","allSubscriptions","Subscription","subscribe","unsubscribe","addNotificationToQueue","title","showSuccessNotification","Success","showErrorNotification","showInfoNotification","Info","showWarningNotification","Warning","useCommandServiceHelper","useTranslation","commandBeforeExecutionCallback","commandSuccessCallback","commandErrorCallback","commandExecutionType","customErrorMessage","commandTimeoutFunction","executeCommandParameter","success","logError","clearTimeout","setTimeout","executeCommandWithoutCallbacks","ConfirmationOverlayContext","ConfirmationOverlayContextProvider","confirmationOverlaySet$","setConfirmationOverlay","showConfirmationOverlay","confirmationOverlayParameters","currentConfirmationOverlayParameters","isDisplayed","hasBeenToggled","hideConfirmationOverlay","useSampleDataDialog","showSampleDataDialog","buttons","onClick","commandService","color","ErrorRoutes","ERROR","PAGENOTFOUND","UNAUTHORIZED","UNLICENSED","SETTINGS_ROOT","SettingsRoutes","BASE","BIDPACKAGES","FEES","GENERALCONDITIONS","GENERALREQUIREMENTS","USERPERMISSIONS","UNITSOFMEASURE","PREFERENCES","ApplicationRoutes","SITE_ROOT","HOME","BID_PACKAGE","BID_SUMMARY","PROJECT","PROJECTS","SETTINGS_BIDPACKAGES","SETTINGS_FEES","SETTINGS_GENERALCONDITIONS","SETTINGS_GENERALREQUIREMENTS","SETTINGS_USERPERMISSIONS","SETTINGS_UNITSOFMEASURE","SETTINGS_PREFERENCES","ERROR_ERROR","ERROR_PAGENOTFOUND","ERROR_UNAUTHORIZED","ERROR_UNLICENSED","NavigationMenu","canLoadSampleData","useMemo","pageIsScrolled_Y","setPageIsScrolled_Y","mobileNavigationMenuIsOpen","setMobileNavigationMenuIsOpen","navigationLinks","setNavigationLinks","loadingProgressBarIsVisible","setLoadingProgressBarIsVisible","userInformation","shouldShowHolidayEasterEgg","today","startOf","month","date","offset","timer","newNavigationLinks","settingsNavigationLink","subLinks","userIsAdmin","userIsProjectAdmin","userIsBidDaySupport","sortOrder","ProjectApi","icon","hasDivider_Top","grayBackground","currentValue","toolsNavigationLink","dataTestId","signIn","generateAndSetNavigationLinks","Navbar","light","fixed","className","to","src","alt","document","body","classList","contains","remove","preventDefault","stopPropagation","currLink","NavLink","tag","Link","data-testid","UncontrolledDropdown","DropdownToggle","nav","caret","DropdownMenu","currSubLink","DropdownItem","divider","hasDivider_Bottom","NavbarToggler","Collapse","isOpen","navbar","Nav","Layout","AuthenticatedRoute","shouldRender","setShouldRender","history","useHistory","redirectUser","requiredUserRoles","allUserRoles","allowAnyRoles","ProjectGuard","useRouteMatch","redirectToError","redirectToUnauthorized","checkUserPermission","SupportOverlayContext","SupportOverlayContextProvider","supportOverlaySet$","setSupportOverlay","showSupportOverlay","supportOverlayParameters","currentSupportOverlayParameters","hideSupportOverlay","forwardRef","buttonStyleCssClass","roundedCorners","Button","innerRef","disabled","tooltip","tabIndex","align","textAlign","getStyles","dataAttributes","PageHeader","SvgImage","image","size","getSizeClass","exclamation","stop","snowflake","getSvgImage","groupFrozenEntitiesData","frozenEntitiesListing","groupedItems","groupBy","metadata2","metadata1","getDisplayTextForEntityType","logWarning","isFrozenEntityNameClickable","FrozenEntitiesAdminPage","pageDataIsLoading","groupedFrozenEntitiesData","setGroupedFrozenEntitiesData","FrozenEntitiesApi","frozenEntitiesListings","frozenEntitiesEditableListings","syncStatus","unfreezeStatus","loadPageData","updateFrozenEntityState","frozenEntityType","newSyncStatus","newUnfreezeStatus","indexToUpdate","copy2","currEntity","onFrozenEntityNameClick","entityName","itemToUpdate","newStatus","GenericErrorPage","PageNotFoundPage","UnauthorizedPage","pageIsDisplayed","setPageIsDisplayed","checkUserAuthenticationStatus","UnlicensedPage","NotificationService","connection","state","SignalR","Connected","withUrl","queryApiBaseUrl","accessTokenFactory","withAutomaticReconnect","configureLogging","build","start","on","onNotificationReceived","callback","onreconnecting","off","onreconnected","notificationHandlers","handler","sourceId","registerForNotifications","onclose","normalizedSourceId","has","numberOfRetries","invokeRegistrationEndpointWithRetry","Promise","recursiveRetry","set","sourceIds","sourceIdsToRegister","invokeBatchRegistrationEndpointWithRetry","requestError","failedSourceIds","Array","isArray","SourceId","Map","HomePageTabs","BTCardsContainerContext","BTCardsContainerHighlightableText","textToDisplay","matchEntireWord","matchStartOfWord","searchTextParts","textToDisplay2","dangerouslySetInnerHTML","__html","cleanUpTextForMatching","inputText","groupCards","cards","enableSort","sortDirection","groupValue","currGroup","currCardListing","sortValue","sortValue2","cardsJSX","groupKey","cardListings","filterCards","cardsToFilter","groupedCards","filteredCardsArray","currCardData","cardMetadata","searchData","matchFound","currSearchTextPart","currMetadata","BTCardsContainer","searchType","minSearchTextLength","setSearchText","filteredCards","setFilteredCards","allCards","setAllCards","allCardsLastValue","columnsCssClass","numberOfCardsPerRow","setFilteredCardsArray","newSearchText","getCardsCountString","filteredCardsCount","sum","cleanedUpSearchText","filteredCardsTimeout","onSearchSubmission","onSearchCallback","enableSearch","Input","autoFocus","placeholder","inputPlaceholderText","onKeyDown","onChange","target","jsxToShowAboveSearchResults","indexOfMatchingCard","copyOfFilteredCards","v2","i2","cardJSX","recordsNotFoundMessage","BTFloatingIconButton","buttonIcon","BTFilterTreeRow","isExpanded","setIsExpanded","isSelected","selectedItems","testIdParts","subItems","testId","allChildrenIds","getAllBTFilterTreeItemChildren","doSelectedChildElementsExist","paddingLeft","level","onSelectCallback","opacity","event","FormFooter","BTDropDownList","defaultItem","placeholderText","label","onChangeHandler","onBlurHandler","displayValueIfNotInList","hasErrors","rest","inputIdentifier","classNames","htmlFor","textField","dataItemKey","onOpen","dispatchEvent","CustomEvent","onBlur","matchingOption","isEqual","getSelectedValue","element","getAttribute","setAttribute","BTRadioGroup","layout","BTModalContext","BTModalContextProvider","modalDisplayStates","setModalDisplayStates","modalIsDisplayed","setModalDisplayValue","modalStates","modalStatesClone","modalId","BTModal","confirmationOverlayDisplayInfoIsDisplayed","setConfirmationOverlayDisplayInfoIsDisplayed","showCloseButton","hideModalResizeButtons","lastOpenState","btModalInnerContentRef","isClosing","setIsClosing","initialModalHeight","modalHeight","setModalHeight","onCloseButtonClick","$event","onModalClosing","shouldClose","timeoutObj","onModalClose","focusTrapOptions","escapeDeactivates","allowOutsideClick","paused","getCssClassesForModalContent","altKey","toUpperCase","modalSaveButton","querySelector","click","modalCloseButton","modalCloseIcon","addExtraSpaceAtBottom","provideFocusTrapCode","NO_GROUPING_OPTION","BTFilterTreeSettingsModal","value1","value2","selectedRadioButtonValue","modalExportData","setModalExportData","availableDropdownOptions1","setAvailableDropdownOptions1","availableDropdownOptions2","setAvailableDropdownOptions2","selectedGroupingDropdownOptions","initialModalDataValues","newDropdownOptionValues","resetSelectedValuesToInitialState","modalInfo","availableRadioButtonOptions","getValueForSorting","generateTreeViewItemFromGroupingProperty","textValue_Other","groupingProperties","displayProperty","currTreeGroupItems","groupingPropertiesIndex","nextGroupingProperty","uniqBy","currItem","groupingPropertiesValues","currProp","newItem","itemsInCurrGrouping","elementsArray","currItem2","BTFilterTree","allOption","filterTreeItems","setFilterTreeItems","showAllOption","setSelectedItems","settingsModalInfo","setSettingsModalInfo","selectedItemsObjects","setSelectedItemsObjects","newItems","items","filterTreeItemIds","flatMap","newSelectedItems","selectedValuesObjects","newObj","isMultiSelect","onSelectedFiltersChange","allBaseLevelChildren","allSelectedIds","indexOfExistingItem","selectedGroupingValues","onSelectedGroupingValuesChange","summaryGroupingProperties","initialSelectedGroupingValues","userCanChangeFilters","disabledFiltersMessage","selectedRadioButtonOptionSuffix","matchingItem","availableGroupingDropdownOptions","showCoolStuff","FrozenEntityNotification","frozenEntityNames","BTTabsContainer","tabs","onTabChange","initialSelectedTab","selectedTab","setSelectedTab","getShortDateString","dateObj","utc","getEEClass","randomNumber1","floor","random","randomNumber2","BTIconButton","BTCard","Card","cardIcons","CardHeader","currCardIcon","CardBody","BTIconButtonToggle","onPointerUp","prefix","smallToggle","getClasses","ProjectDetailRow","aria-label","getAreaText","area","getAddressTextFromProjectSearchResult","address_StreetAddress","address_AptSuiteBldg","address_City","address_StateOrRegion","address_PostalCode","ProjectSearchResultCard","canEditProject","userCanEditOrDeleteProject","isFrozen","projectImageBlobUrl","setProjectImageBlobUrl","currentProjectImageUri","imageBlobUrl","getProjectImageUrl","projectUrl","lastAccessedDate","toDate","Dropdown","dropdownIsOpen","toggle","onMenuButtonClick","direction","projectEditUrl","backgroundImage","defaultProjectImage","grandTotal","ProjectPropertyNamesToSearch","getFilteredProjects","projectsToFilter","filtersToApply","currProject","currProjectMatchesAnyFilterCriteria","currSelectedFilterObject","allCurrFilterCriteriaWasMatched","currFilterKeyValue","HomePage","generateBTCardListing","recentProjects","setRecentProjects","allProjects","setAllProjects","allProjectsHasBeenViewed","setAllProjectsHasBeenViewed","allProjectsEnhancedTimeSearchIsActive","setAllProjectsEnhancedTimeSearchIsActive","lastSearchTextForAllProjects","setLastSearchTextForAllProjects","RecentProjects","AllProjects","filterTreeGroupingDropdownOptions","bidDayApplicationEntityIsFrozen","setBidDayApplicationEntityIsFrozen","systemSettingsEntityIsFrozen","setSystemSettingsEntityIsFrozen","currentTab","setCurrentTab","openDropdownRecordId","setOpenDropdownRecordId","selectedFilters_RecentProjects","setSelectedFilters_RecentProjects","selectedFilters_AllProjects","setSelectedFilters_AllProjects","selectedModalData_RecentProjects","setSelectedModalData_RecentProjects","selectedModalData_AllProjects","setSelectedModalData_AllProjects","filterDisplayProperty_RecentProjects","setFilterDisplayProperty_RecentProjects","filterDisplayProperty_AllProjects","setFilterDisplayProperty_AllProjects","filterGroupingProperties_RecentProjects","setFilterGroupingProperties_RecentProjects","filterGroupingProperties_AllProjects","setFilterGroupingProperties_AllProjects","filterGroupingPropertiesSummary_RecentProjects","setFilterGroupingPropertiesSummary_RecentProjects","filterGroupingPropertiesSummary_AllProjects","setFilterGroupingPropertiesSummary_AllProjects","signalRBroadcast_Settings$","onSignalRBroadcast_Settings","bidDayApplicationEntityIsFrozenResult","systemSettingsEntityIsFrozenResult","SettingsApi","projectViewSettingsForUser_Recent","projectViewSettingsForUser_All","projectViewSettingsForUser_RecentProjects","projectViewSettingsForUser_AllProjects","isAllProjects","availableOptions","groupingKey1_RecentProjects","groupingKey2_RecentProjects","groupingKey1_AllProjects","groupingKey2_AllProjects","selectedRadioButtonValue_AllProjects","RecentProjectsApi","recentProjectsArray","initializeData","hasOwnProperty","logDebug","entityFrozenMessage","IsFrozen","registerForSettingsChangeNotifications","currSourceId","unregisterFromNotifications","onModalDataChange","settingsType","currSelectedRadioButtonValue","allProjectsArray","projectType","selectedFilters","getProjectsCardsListings","filteredProjects","canUserEditOrDeleteProject","userCanCopyProject","onSearchCallback_AllProjects","ignoreDateRange","exactMatchProjects","projectsArray","frozenEntitiesNameStrings","getFrozenEntitiesNames","selectedTabId","LinksConstants","BECKTECH_WEBSITE","BECKTECH_COMMUNITY_WEBSITE","LoginPage","userIsAuthenticated","getUrlForDisplay","websiteUrl","websiteUrlCommunity","href","CreateBidPackageDefinitionCommand","DeleteBidPackageDefinitionCommand","UpdateBidPackageDefinitionCodeCommand","updatedNumber","updatedCode","UpdateBidPackageDefinitionDescriptionCommand","updatedDescription","CreateTradeRequirementDefinitionCommand","UpdateTradeRequirementDefinitionDescriptionCommand","UpdateTradeRequirementDefinitionIndexCommand","updatedIndex","UpdateTradeRequirementDefinitionRequirementFulfillmentTypeCommand","DeleteTradeRequirementDefinitionCommand","BidPackageMaintenanceBatchCommand","DispatchManagerContext","getDispatchData","dispatchDataObj","Feature","DispatchManagerContextProvider","allDispatchData","setAllDispatchData","reducers","setReducers","registerReducers","newReducers","existingReducers","existingReducersCopy","reducersCollectionToModify","currNewReducer","unregisterReducer","reducerToRemove","indexOfReducer","newArray","runReducersAgainstData","action","matchingReducerCollection","currReducer","setDispatchData","existingDispatchData","dispatchAction","dataToModify","dataToModifyCopy","existingDispatchDataCopy","dispatchData","useDispatcherWithCommandManagerService","componentDispatchData","initializeCommandManagerServiceOnDispatcher","groupId","commandManagerService","generateBatchCommandInitializerReducer","commandBatchClass","dispatchDataCommands","getCommands","commandManager","addCommand","commandManagerDispatchReducer","clearCommands","addCommandToBatchCommandObject","commandToAdd","clonedCommandManagerService","batchCommandObject","getBatchCommandObjectFromCommandManager","BTSearchBar","useDegradedActionNotifications","componentName","onDegradedActionStarted","offDegradedActionStarted","onDegradedActionFinished","IsSuccess","reload","offDegradedActionFinished","DragHandle","SortableHandle","SortableItem","SortableElement","isEditable","isSortable","SortableList","SortableContainer","BTSortableContainer","onSortEnd","useDragHandle","helperClass","ghostRowCssClass","renderBTSortableContainer","BidPackageEntityLimits","Code_MaxLength","Description_MaxLength","Notes_MaxLength","EntityValidationConstants","AlternateEntityLimits","Name_MaxLength","AdjustmentEntityLimits","BidderEntityLimits","CompanyName_MaxLength","PhoneNumber_MaxLength","FaxNumber_MaxLength","PrimaryContactName_MaxLength","PrimaryContactEmail_MaxLength","BidPackageLineItemEntityLimits","Metadata_MaxLength","FeeEntityLimits","GeneralConditionEntityLimits","ProjectEntityLimits","Subtitle_MaxLength","StreetAddress_MaxLength","AptSuiteBldg_MaxLength","City_MaxLength","StateOrRegion_MaxLength","Country_MaxLength","PostalCode_MaxLength","Architect_MaxLength","Owner_MaxLength","RequirementEntityLimits","RequirementFulfillmentEntityLimits","Value_MaxLength","UnitOfMeasureEntityLimits","UserEntityLimits","Email_MaxLength","Location_MaxLength","Roles","Name","textAlignment","TradeRequirementsListing","errors","tradeRequirementDefinition","addTradeRequirementDefinition","updateTradeRequirementDefinition","deleteTradeRequirementDefinition","validateTradeRequirementDefinition","definition","setDefinition","definitionCopy","isFocused","radioButtonOptions","Quantitative","Qualitative","Freeform","addButtonClick","descriptionChangeHandler","updatedDefinition","descriptionBlurHandler","requirementFulfillmentTypeChangeHandler","maxLength","BidPackageDefinitionListing","bidPackageDefinition","isReadOnly","tradeRequirementsAreEditable","executeBatchCommands","editBidPackageDefinitionButtonClick","deleteBidPackageDefinitionButtonClick","onEditTradeRequirementsCallback","onSaveCallback","onDiscardCallback","setIsOpen","setErrors","setIsEditable","bidPackageDefinitionToEdit","setBidPackageDefinitionToEdit","duplicateDescriptionError","emptyDescriptionError","generateNewTradeRequirementDefinition","newTradeRequirementDefinition","setNewTradeRequirementDefinition","onSubmit","discardChanges","onDiscard","setTradeRequirementErrors","errorMessages","updatedErrors","u","descriptions","tradeRequirement","updatedTradeRequirements","idx","definitionHasErrors","renderTradeRequirementListings","oldIndex","newIndex","updatedDefinitions","previousDefinition","uniq","errorMessage","BidPackageDefinitionListingContainer","bidPackageIdOfTradeRequirementsBeingEdited","setBidPackageIdOfTradeRequirementsBeingEdited","bidPackageDefinitions","Fragment","bidPackageDefinitionDispatchKey","executeBatchCommandCallback","getFormErrorMessages","stringValues","getStringValues","val","FormErrorContainer","containerCssClass","uniqueErrorMessages","currErrorMessage","useFocusOnRender","inputRef","input","focus","WrappedInput","field","form","hasBeenTouched","touched","submitCount","FormTextInput","validator","validate","component","BidPackageEditForm","onSubmitClick","onDiscardClick","FormSchema","Yup","shape","required","previousValidCode","setPreviousValidCode","codeValidator","initialValues","validationSchema","bidPackageMaintenanceReducer","BidPackageMaintenancePage","isEditAreaOpen","setIsEditAreaOpen","setBidPackageDefinitions","bidPackageMaintenancePageEditAreaRef","filterTimeout","setFilterTimeout","systemSettingEntityIsFrozen","setSystemSettingEntityIsFrozen","useCommandManagerDispatcher","batchCommandInitializerReducer","executeBatchCommand","commandManagerObj","newCommandManagerService","executeNextCommand","entityIsFrozen","BidPackageMaintenanceApi","loadBidPackageDefinitions","toggleCollapse","open","closeEditAreaAndClearOutEditModel","updatedBidPackageDefinitions","sortedDefinitions","bidPackageDefinitionsClone","bidPackageDefToUpdate","errorMessageFromServer","onDeleteClick","onSearchTextChange","filteredBidPackageDefinitions","getSortedBidPackageDefinitions","bidPackageDefs","sortedBidPackageDefs","trd","getDisplayedBidPackageDefinitions","UpdateFeeDefinitionAmountCommand","UpdateFeeDefinitionOrderCommand","UpdateFeeDefinitionNameCommand","updatedName","UpdateFeeDefinitionFeeTypeCommand","CreateFeeDefinitionCommand","DeleteFeeDefinitionCommand","FeesBatchCommand","convertFeeTypeToFeeTypeOption","Bid","Total","Subtotal","LumpSum","convertFeeTypeToFeeTypeName","allowedNonNumericKeys","BTNumericInput","allowAnyKeysToPassThrough","nonNumericKeysToPassThrough","formatStringForNumericComponent","lastKeyPressedWasUpOrDownArrowKey","setLastKeyPressedWasUpOrDownArrowKey","onKeyDownHandler","ctrlKey","currentInput","addEventListener","removeEventListener","valToPassToInput","onFocus","parsedFloat","parseFloat","num","step","spinners","FeeTableItem","fee","feeTypeDropDownListOptions","isAdding","addFee","deleteFee","updateFee","validateFee","feeToEdit","setFeeToEdit","validFee","setValidFee","updateLocalAndParentState","updatedFee","nameChangeHandler","amountChangeHandler","typeChangeHandler","option","referenceFee","cleanedUpFee","generateFeesTotal","bidTotal","fees","cur","FeeTable","initialFees","addFeeCallback","deleteFeeCallback","updateFeeCallback","onSortEndCallback","calculateFeesCallback","onSaveClick","discardCallback","DEFAULT_FEETYPE_SELECTION","setBidTotal","setFees","isAddingFeeOrSubtotal","setIsAddingFeeOrSubtotal","feesRef","calculateFeesPromiseRef","feeTypeOptions","getFilteredFeeTypeDropDownListOptions","feeHasErrors","setFeeErrors","trimmedName","names","f","calculateFees","updatedFees","currentPromise","then","feesCallbackResponse","mostRecentFees","feeCallbackResponse","responseFee","isValid","feesClone","updatedFeeTypeOption","generateNewFeeOrSubtotal","isSubtotal","newFee","feesHaveBeenModified","omit","generatedFeeTable","previousFee","feesReducer","FeesPage","savedFees","setSavedFees","loadInitialData","convertToFeeDefinition","convertToFeeDTO","feesToCalc","baseCost","convertedFees","FeeApi","calculatedFees","feeToCheck","calculatedFee","feeToReturn","loadDataFromAPI","loadFeesFromAPI","feesToSet","CreateGeneralConditionsBidPackageDefinitionCommand","UpdateGeneralConditionsBidPackageDefinitionCodeCommand","UpdateGeneralConditionsBidPackageDefinitionDescriptionCommand","CreateBidPackageLineItemDefinitionCommand","DeleteBidPackageLineItemDefinitionCommand","UpdateBidPackageLineItemDefinitionDescriptionCommand","UpdateBidPackageLineItemDefinitionIndexCommand","UpdateBidPackageLineItemDefinitionUnitOfMeasureCommand","GeneralConditionsBatchCommand","GeneralConditionsEditForm","generalConditionsDefinition","handleCodeBlur","handleDescriptionBlur","handleBlur","setFieldValue","LineItemListItem","lineItemDefinition","availableUnitsOfMeasure","addLineItemDefinition","deleteLineItemDefinition","updateLineItemDefinition_OnChange","updateLineItemDefinition_OnBlur","validateLineItemDefinition","definitionToEdit","setDefinitionToEdit","validDefinition","setValidDefinition","filteredErrors","setFilteredErrors","availableUnitOfMeasureListOptions","setAvailableUnitOfMeasureListOptions","deleteButtonClick","unitOfMeasureChangeHandler","unitOfMeasureBlurHandler","hasPropertySpecificErrors","property","useGeneralConditionContainer","addLineItemDefinitionCallback","deleteLineItemDefinitionCallback","updateLineItemDefinitionCallback","onSubmitClickCallback","onDiscardClickCallback","generalConditionDefinition","setGeneralConditionDefinition","generalConditionDefinitionToEdit","setGeneralConditionDefinitionToEdit","setLineItemDefinitions","definitionsCopy","setAvailableUnitsOfMeasure","newLineItemDefinition","setNewLineItemDefinition","existingBidPackageDefinitions","setExistingBidPackageDefinitions","isGeneralConditionDetailsEditable","setIsGeneralConditionDetailsEditable","isLineItemsEditable","setIsLineItemsEditable","lineItemErrors","setLineItemErrors","setCurrentGeneralCondition","generalCondition","updateLineItemErrors","generateNewLineItemDefinition","UnitOfMeasureApi","unitsOfMeasure","uom","loadUnitsOfMeasure","initializeExistingLineItemDefinitions","definitionId","originalDefinition","generateGeneralConditionDetailsSection","generateGeneralConditionLineItemsSection","generatedLineItemElements","li","generalConditionsReducer","GeneralConditionsPage","generalConditionToEdit","setGeneralConditionToEdit","updateLineItemDefinition","resetGeneralConditions","isNewGeneralConditions","definitionToSet","existingBidPackages","parseInt","generalConditions","loadGeneralCondition","CreateGeneralRequirementDefinitionCommand","DeleteGeneralRequirementDefinitionCommand","UpdateGeneralRequirementDefinitionDescriptionCommand","UpdateGeneralRequirementDefinitionIndexCommand","UpdateGeneralRequirementDefinitionRequirementFulfillmentTypeCommand","GeneralRequirementsBatchCommand","RequirementsConstants","QUANTITATIVE","QUALITATIVE","FREEFORM","RequirementsList","requirementDefinition","addRequirementDefinition","deleteRequirementDefinition","updateRequirementDefinition_OnChange","updateRequirementDefinition_OnBlur","updateRequirementFulfillmentType","validateRequirementDefinition","useRequirementList","addRequirementDefinitionCallback","deleteRequirementDefinitionCallback","updateRequirementDefinitionCallback","setDefinitions","newGeneralRequirementDefinition","setNewGeneralRequirementDefinition","generateNewGeneralRequirementDefinition","setRequirementDefinitions","setRequirementErrors","generateRequirementList","requirementDefinitions","requirementErrors","generatedRequirementList","generateAddGeneralRequirementDefinitionRow","generateAddTradeRequirementDefinitionRow","generalRequirementsReducer","GeneralRequirementsPage","timeoutForPageLoadingOverlay","setTimeoutForPageLoadingOverlay","savedGeneralRequirementDefinitions","setSavedGeneralRequirementDefinitions","onAllEventsForCommandProcessed","offAllEventsForCommandProcessed","addGeneralRequirementDefinition","deleteGeneralRequirementDefinition","updateGeneralRequirementDefinition","GeneralRequirementsApi","loadGeneralRequirementDefinitions","UpdateMeasurementSystemCommand","UpdateBiddersRangesCommand","PreferencesBatchCommand","WrappedNumericTextInput","FormNumericTextInput","PreferencesEditForm","typeError","oneOf","integer","min","FormikEffect","connect","onFormChanged","formik","formPreferences","newMidMax","preferencesReducer","PreferencesPage","preferencesToEdit","setPreferencesToEdit","PreferencesApi","pref","loadPreferences","UnitOfMeasureForm","uniqueUnitValidator","unit","actions","onAddClick","resetForm","UnitOfMeasureListing","getNewUnitOfMeasure","UnitsOfMeasurePage","unitOfMeasureToEdit","setUnitOfMeasureToEdit","setUnitsOfMeasure","units","newUnit","newUnits","updatedUnits","LocationListing","locations","setLocation","currLocation","WrappedComboBox","allowCustom","FormComboBox","getValueForMultiSelect","fv","WrappedMultiSelect","autoClose","newValues","FormMultiSelect","UserRoleSchema","UserEditForm","of","getAvailableUserRoles","uniqueEmailValidator","emailAddress","clientDomains","domains","domain","emailAddressDomain","pop","rolesValidator","newRoles","UserListing","editUserButtonClick","deleteUserButtonClick","currentUser","isUserCurrentUser","isUserHigherRole","isUserAdminOrProjectAdmin","currRole","UserPermissionsPage","userToEdit","setUserToEdit","setUsers","setDomains","setLocations","locationsToDisplay","setLocationsToDisplay","filteredUsers","setFilteredUsers","userPermissionsPageEditAreaRef","userIsAdminOrProjectAdmin","updateLocations","newLocations","sort","loadUsers","newUser","newUsers","usersClone","onEditClick","updatedUsers","ClearSelectedBidderOnBidPackage","DeleteBidPackageBidderCommand","DeleteBidPackageLineItemCommand","DeleteBidderRequirementFulfillmentOnBidPackageCommand","DeleteLineItemBidOnBidPackageCommand","SetBidderOrderCommand","SetBidderStatusCommand","SetSelectedBidderOnBidPackage","selectedBidderCompanyName","UpdateBidPackageLineItemOrderCommand","alternameName","alternateName","UpdateBidPackageLineItemGroupOrderCommand","classifications","BidPackageConstants","Config","BID_PACKAGE_AUTOSAVE_TIMEOUT","BID_PACKAGE_LINEITEMS_ADD_THRESHOLD","BID_PACKAGE_LINEITEMS_PERFORMANCE_THRESHOLD","GridSectionIds","ADJUSTMENTS","ADJUSTMENTS_BID_PACKAGE_TOTALS","BID_PACKAGE_HEADER","BID_PACKAGE_TOTALS","REQUIREMENTS","LINE_ITEMS","LINE_ITEMS_HEADER","BTGridContainerContext","BTGridContainerContextProvider","rowMouseEnter$","onRowMouseEnter","rowMouseLeave$","onRowMouseLeave","itemsReordered$","onItemsReordered","rowCheckboxClick$","onRowCheckboxClick","rowClick$","onRowClick","setCellRef$","onSetCellRef","dragStatusChanged$","onDragStatusChanged","selectedRowsChange$","onSelectedRowsChange","collapsedRowsChange$","onCollapsedRowsChange","rerenderStatus","setRerenderStatus","elementBeingDragged","lastMouseCoordinates","rowHeightCollections","itemBeingDraggedInfo","mouseMoveEventTimer","mouseMoveEventHandler","pageXOffset","y","pageYOffset","onPointerUpEvent","passive","FeatureFlagContext","FeatureFlagContextProvider","featureFlags","setFeatureFlags","features","flags","feature","startsWith","getFeatureFlagsFromLocalStorage","featureIsEnabled","ProjectInfoModal","streetAddressString","cityStateString","country","useProject_Info","projectInfoModalState","setProjectInfoModalState","showProjectInfo","onProjectInfoModalClose","curr","getProjectInfoJSX","BTGridDraggedElement","clonedDraggedElement","elementBeingDraggedBoundingRect","getBoundingClientRect","ghostElement","cloneNode","width","transform","height","left","appendChild","position","zIndex","userSelect","transitionDuration","mouseVerticalOffset","mouseHorizontalOffset","removeChild","getElementOffset","el","rect","scrollLeft","documentElement","scrollTop","BTContextMenuContext","BTContextMenuContextProvider","contextMenuOpen$","openContextMenu","BTDropdownMenuItem","secondaryText","isDivider","BTContextMenu","shouldAllowInputToTriggerContextMenu","additionalItemsJSX","contextMenuContainerElement","contextMenuDropdownIsOpen","setContextMenuDropdownIsOpen","lastClickedCoordinates","setLastClickedCoordinates","subscription","getItemsForDisplay","itemsToDisplay","lastItem","currContextMenuItem","onContextMenu","targetIsInputElement","persist","boundsOfDropdownContainer","clickCoordinate_X","clientX","clickCoordinate_Y","clientY","xCoordinate","frozenCellShouldMove_X","cell","frozenCell_InitialXOffset","pageScrollOffset_X","frozenOnHorizontalScroll","frozenCellShouldMove_Y","frozenCell_InitialYOffset","pageScrollOffset_Y","frozenOnVerticalScroll","anchorElementSelector","bottom","getCellClass","cellWidthType","cellHorizontalAlignment","cellVerticalAlignment","cellBackgroundColor","isHovered","trimTextOnOverflow","getHorizontalAlignmentCSSClass_FlexDisplay","generateRandomColor","colors","getCellStyle","minHeight","rowHeight","currCell","isPlaceholderForHorizontalFrozenCell","amountToMoveFrozenCell","isPlaceholderForVerticalFrozenCell","anchorOffset","background","borderRadius","maxHeight","getAdditionalStylesClasses","cellAdditionalStyles","BTGridRowCell","collapseDirection","collapsibleIconJSXElementFactory","gridSectionId","cellIndex","isCollapsed","isCollapsibleTrigger","isPrimaryGridRow","elementKey","rowGroupingLevel","rowNumber","frozenCellRef_X","frozenCellRef_Y","setPageScrollOffset_X","setPageScrollOffset_Y","cellIsFrozen_X","cellIsFrozen_Y","newOffset","cellStyle","leftOffsetOfNonPlaceholderElement","offsetLeft","leftOffset","cellContentToRender","cellContentWhenCollapsed","cellContent","doesCellDisplayContent","Children","cellTriggersBTPopover","cellWidth","cellAdditionalCollapseStyles","cellAdditionalUncollapseStyles","onMouseEnter","onCellMouseEnter","onMouseLeave","onCellMouseLeave","cellContentAdditionalClassNames","isChevronRotated","innerElement","getCollapsibleIconJSX","mouseEventNoOpHandler","BTGridRow","btGridRow","correspondingPrimaryGridSectionGridRow","collapseOrSelectGroupingKey","shouldRespondToMouseEvents","rowHeightCollectionForGridSection","rowHeights","previousRerenderId","dragAndDropResponseTimeout","setIsHovered","setIsSelected","isActiveDragAndDropTarget_Bottom","setIsActiveDragAndDropTarget_Bottom","isActiveDragAndDropTarget_Top","setIsActiveDragAndDropTarget_Top","isActiveDragAndDropTarget_Left","setIsActiveDragAndDropTarget_Left","isActiveDragAndDropTarget_Right","setIsActiveDragAndDropTarget_Right","isInvalidDropTarget","setIsInvalidDropTarget","setIsCollapsed","isVisible","setIsVisible","rerenderId","updateCollapseStateVariable","newCollapsedItems","groupingKey","rowMetadataMappings","rowGroupingInfo","groupingInfo","updateVisibleStateVariable","globalCollapseTriggerKey","globalCollapseResponseKey","isSelectable","rowId","collapsedItems","onRowClick_CollapsibleRow","HTMLInputElement","sortableContainerId","sortableInfo","isGroupedRow","groupingLevel","groupingParent1Info","groupingParent2Info","onRowClick_SelectableRow","onRowClickHandler_Collapse","onRowClickHandler_Select","onMouseEnterHandler","getDropTargetStatus","rowBeingDraggedIsGroupingRow","thisRowIsGroupingRow","draggedRowGroupingLevel","dropTargetGroupingLevel","draggedRowGroupingKey1","draggedRowGroupingKey2","dropTargetGroupingKey1","dropTargetGroupingKey2","isTheLastElementOfGroupingKey1Parent","isTheLastElementOfThisParent","isTheLastElementOfGroupingKey2Parent","sortableDirection","onMouseLeaveHandler","onMouseMoveHandler","dropTargetStatus","targetElement","closest","rowMidPoint","btGridRowAsPrimary","dragStartedTimeout","data-rownumber","data-collapsed","data-displayed","isHoverable","showBottomBorder","bottomBorderColor","getRowClass","onMouseMove","dragInfo","dropTarget","dropDirection","onPointerDown","selectableCellAdditionalStyles","readOnly","checked","returnValue2","contextMenuItems","contextMenuItemsJSX","BTSubGrid","subGrid","primarySubGrid","auxiliaryRows","currGridSectionRow","currRowNumber","BTGridContainerGridSection","addTopMargin","gridSectionZIndexBase","getPrimaryGridStyle","setPrimaryGridRef","gridSection","primaryGrid","secondaryGrids","currSecondaryGrid","currSecondaryGridZIndex","addLeftPadding","eeKeyboardSequence","useBTGridContainerKeyboardNavigation","gridRowReferenceCollections","currentKeyboardEntry","lengthOfKeyboardEntry","key2","allInputElements","gridRowReferences","currGridRowReference","gridCellReferences","currGridCellReference","inputElements","querySelectorAll","currInputElement","currInputElementAsHtmlElement","topOffset","matchingInputElement","allInputsOnRow","indexOfTargetElement","elementToFocus","shouldMoveLeft","shiftKey","shouldMoveRight","orderedRowNumbers","indexOfMatchingElementsRow","sortedElementsOnNextRow","lastItemOfPrevRow","blur","firstItemOfNextRow","centerOffsetOfTargetElement","offsetWidth","elementsThatIntersectTargetElementCenter_GiveOrTake50Feet","BTGridContainerInnerComponent","gridSections","gridRerenderTriggerObject","isFullWidth","primaryGridZIndex","primaryGridReferences","selectedRowsCopy","isDraggingItem","setIsDraggingItem","primaryGridsWidth","setPrimaryGridsWidth","collapsedRowsCopy","gridIsInitialized","previousGridRerenderTriggerObject","previousRerenderStatus","setCellRef","matchingGridRowReferenceCollection","indexOfExistingCellReference","resetCalculatedDimensions_PrimaryGridWidths","resetCalculatedDimensions_RowHeights","currRowHeightCollection","recalculateDimensions_PrimaryGridWidths","allPrimaryGridWidths","recalculateDimensions_RowHeights","newRowHeightsCollection","currGridRowReferenceCollection","newRowHeightCollection","offsetHeight","newVal","existingItemIndex","childRows","currGridSection","rowsToAdd","elementsToAdd","currChildRow","allChildRowIds","initializeCollapsedStates","groupingKeyToFind","gridSectionEntry","allRowsInCurrGridSection","defaultItemsToCollapse","isCollapsedByDefault","rowData","minWidth","useLayoutEffect","rowsChanged","primaryGridColumnsChanged","resizeEventCallback","resizeEventHandler","auxiliaryRowsInPrimaryGrid","regularRowsInPrimaryGrid","gridSectionIndex","BTGridContainer","BidPackagePageContext","BidPackagePageContextProvider","adjustmentNotesOpen$","adjustment_OpenNote","adjustmentNotesSave$","adjustment_SaveNote","adjustmentChange$","adjustment_Change","adjustmentBlur$","adjustment_Blur","bidderEditDocuments$","bidder_EditDocuments","bidderEditNotes$","bidder_EditNotes","bidderShowInfo$","bidder_ShowInfo","bidderDelete$","bidder_Delete","bidderEdit$","bidder_Edit","bidderSelect$","bidder_Select","biddersAdd$","bidders_Add","lineItemChange$","lineItem_Change","lineItemBlur$","lineItem_Blur","lineItemsAdd$","lineItems_Add","lineItemDelete$","lineItem_Delete","lineItemsDelete$","lineItems_Delete","lineItemEdit$","lineItem_Edit","lineItemsEdit$","lineItems_Edit","lineItemBidChange$","lineItemBid_Change","lineItemBidBlur$","lineItemBid_Blur","lineItemBidFocus$","lineItemBid_Focus","lineItemRollupBidChange$","lineItemRollupBid_Change","lineItemRollupBidBlur$","lineItemRollupBid_Blur","requirementFulfillmentBlur$","requirementFulfillment_Blur","requirementFulfillmentChange$","requirementFulfillment_Change","requirementFulfillmentFocus$","requirementFulfillment_Focus","lockBidPackage$","lockBidPackage_Change","bidPackageNotes$","bidPackageNotes_Open","keyboardShortcutsInfoIsOpen$","keyboardShortcutsInfoIsOpen_Change","selectedLineItemsMappings$","selectedLineItemsMappings_Change","viewProjectInfo$","viewProjectInfo_Open","useBidPackagePageContext","AddLineItemToBidPackageCommand","UpdateBidPackageLineItemCommand","BTItemsManagerGridAutoCompleteCell","autoCompleteComponent","handleChange","syntheticEvent","existingValue","addListValue","setState","opened","onPasteHandler","testIdPrefix","dataIndex","onPaste","listValues","dataItem","nativeEvent","BTItemsManagerGridDropdownCell","popupSettings","appendTo","listAnchor","BTItemsManagerGridNumericCell","isExtendedPrecisionFormat","BTItemsManagerGridTextCell","dataValue","valid","validationFn","AddEditLineItemsForm","mode","lineItemsToEdit","onFormTouch","isAddMode","level1Classifications","setLevel1Classifications","level2Classifications","setLevel2Classifications","fetchMetadata","projectMetadata","changed","metadataChanged","setLineItems","addNewLineItem","newLineItem","removeLineItem","addNewLevel1Classification","addNewLevel2Classification","handlePaste","clipboardData","getData","eventAsAny","columnIndexOfOriginCell","columnIndex","rowIndexOfOriginCell","rowIndex","parseLineItemInputsFromRow","unshift","parsedRowData","currLineItems","newLineItems","currRow","parsedRowDataForCurrRow","command","originalLineItem","oli","updatedLineItem","deleteLineItemButton","gridContainer","descriptionTextInput","gcp","quantityNumericInput","unitOfMeasureDropList","unitPriceNumericInput","classificationLevel1DropList","classificationLevel2DropList","validateLineItems","lineItemsToValidate","validationErrors","desc","validateAndSave","itemChanged","editedLineItems","editField","onItemChange","headerClassName","KeyboardShortcutsInformation","info","groups","listings","currListing","currListingIndex","currKeyboardKeySet","currKeyboardKeySetIndex","currKeyboardKey","currKeyboardKeyIndex","circleColor","BidPackageKeyboardShortcuts","keyboardShortcutsInfo","typeToColorMap","warning","BTAlert","Alert","NotificationServiceStatusMessage","alert","setAlert","isNotificationServiceReconnecting","onReconnecting","onReconnected","onClose","offReconnecting","offReconnected","offClose","alertToUse","liveUpdatesRegistrationFailed","BidPackagePageHeader","allBidPackageDropdownOptions","anyEntitiesAreFrozen","bidPackageNotes","bidPackageTooltip","canLockBidPackage","liveUpdateRegistrationFailed","onSelectedBidPackageChange","projectInfo","selectedBidPackageId","navigator","clipboard","writeText","DeleteAdjustmentOnBidPackageCommand","SetAdjustmentOnBidPackageCommand","newBidAmount","onChangeCallback_Adjustment","currentBidPackage","bidPackageCopy","existingAdjustment","getAdjustment","setAdjustment","onBlurCallback_Adjustment","originalBidPackage","projectAlternates","getBidder","shouldSetAdjustment","commandToProcess","successFunction_Adjustment","bidPackageToUpdate","bidPackageWithUpdatedData","getBidderByCompanyName","deleteAdjustment","adjustmentToAddOrUpdate","errorFunction_Adjustment","adjustmentToRestore","useBidPackageBidHandler_Adjustments","SetLineItemBidOnBidPackageCommand","onChangeCallback_LineItemBid","existingBid","getLineItemBid","updatedBid","setLineItemBid","onBlurCallback_LineItemBid","matchingOriginalBid","bidValueIsValid","isBidValid","shouldAddOrUpdateBid","successFunction_LineItemBid","deleteLineItemBid","bidToAddOrUpdate","errorFunction_LineItemBid","bidToRestore","useBidPackageBidHandler_LineItemBids","DeleteLineItemRollupBidOnBidPackageCommand","metadataValues","SetLineItemRollupBidOnBidPackageCommand","onChangeCallback_LineItemRollupBid","existingRollupBid","getLineItemRollupBid","setLineItemRollupBid","onBlurCallback_LineItemRollupBid","matchingAlternate","successFunction_LineItemRollupBid","deleteLineItemRollupBid","errorFunction_LineItemRollupBid","useBidPackageBidHandler_LineItemRollupBids","SetBidderRequirementFulfillmentOnBidPackageCommand","onChangeCallback_RequirementFulfillment","existingRequirement","existingFulfillment","getRequirementFulfillment","setRequirementFulfillment","deleteRequirementFulfillment","onBlurCallback_RequirementFulfillment","matchingRequirement","matchingExistingFulfillment","fulfillmentShouldBeSet","fulfillmentShouldBeDeleted","isFulfillmentValid","isExistingFulfillmentValid","fulfillmentTextValue","commandToProcess2","successFunction_RequirementFulfillment","getRequirementByDescription","fulfillmentToAddOrUpdate","errorFunction_RequirementFulfillment","fulfillmentToRestore","useBidPackageBidHandler_RequirementFulfillments","AddEditBidPackageNotesToBidPackageCommand","bidPackageNotesId","FormTextAreaInput","BTNotes","onCloseClick","UpdateBidPackageLockCommand","useBidPackage","bidPackageNotesToEdit","bidPackageNotesModalState","setBidPackageNotesModalState","openBidPackageNotes","onBidPackageNotesDiscard","onBidPackageNotesChange","newNotes","onBidPackageNotesChangeCallback","onBidPackageNotesModalClose","getBidPackageNotesJSX","successFunction_SelectedBidder","clearSelectedBidder","setSelectedBidder","errorFunction_SelectedBidder","previouslySelectedBidderId","onLockChangeCallback","successFunction_Lock","errorFunction_Lock","AddEditAdjustmentNotesToBidPackageCommand","adjustmentNotesId","useBidPackageAdjustments_Notes","adjustmentToEdit","modalState","setModalState","editAdjustmentNotes","adjustment","closeAdjustmentNotesModal","onAdjustmentNotesSave","onAdjustmentNotesDiscard","getAdjustmentNotesJSX","AddBidderToBidPackageCommand","UpdateBidPackageBidderCommand","AddEditBiddersForm","existingBidders","bidderToEdit","onEditedBiddersChange","setBidders","newBidder","sb","onItemChanged","editedBidder","editedBidders","parseBidderInputsFromRow","currBidders","newBiddersArray","requiredTextInput","textInput","isFaxNumberField","cleanedUpValue","deleteButton","validateBidders","duplicateNames","bidderInEdit","indexOfOriginalCompanyName","initialModalState","useBidPackageBidders_AddEditForm","onBiddersSaveCallback","addBidders","editBidder","onBiddersSave","addCommands","BidPackageApi","editCommands","shouldDiscardBidderChanges","editFieldsToOmit","onBiddersDiscarded","getBiddersAddEditJSX","DeleteBidPackageBidderDocumentCommand","BTUpload","setAuthHeaders","setHeaders","reference","autoUpload","multiple","batch","withCredentials","restrictions","maxFileSize","onAdd","files","newState","onBeforeUpload","additionalFormData","additionalData","onBeforeFileUpload","fileNames","fu","onStatusChange","onFileUploadComplete","saveUrl","saveHeaders","LinkButton","alignment","BidderDocumentsForm","setErrorMessage","getCardIcon","getFileExtension","MaxNumFilesSelected","existingFileNames","bidderFileUploads","duplicatedFileNames","duplicatedFileNameString","validateBeforeFileUpload","doc","formattedUploadDate","onDownloadDocumentClick","onDeleteDocumentClick","BidderDocumentsModal","bidderFileUploadsContainerId","previousSourceId","setBidderFileUploads","isDataLoaded","loadBidderFileUploads","bidderFileUploadsResults","SourceIds","deleteBidderDocument","docName","downloadBidderDocument","bidderDoc","downloadUrl","modalIsOpen","useBidPackageBidders_DocumentsModal","setModalIsOpen","showBidderDocumentsModal","getBidderDocumentsModalJSX","BidderInfoModal","useBidPackageBidders_InfoModal","showBidderInfo","onBidderInfoModalClose","getBidderInfoJSX","AddEditBidderNotesToBidPackageCommand","bidderNotesId","useBidPackageBidders_Notes","onBidderNotesChangeCallback","editBidderNotes","closeBidderNotesModal","onBidderNotesChange","bidderCopy","onBidderNotesDiscard","getBidderNotesJSX","generateEmptyGridRow","generateEmptyGridRow_Primary","generateEmptyGridRow_Base","generateEmptyGridRowWithEmptyCells","gridCellsToCreate","gridCellsWidth","generateEmptyGridRowWithEmptyCells_Primary","generateEmptyGridRowWithNoCells_Primary","generateEmptyGridRowWithEmptyCells_Base","generateGridRow_Grouped","newRowObj","BTPopoverContext","BTPopoverContextProvider","displayedPopoverInfo$","setDisplayedPopoverInfo","BidderSelectElement","isDisabled","matchingEnumKey","bidClassificationOptions","onBidFocusCallback","onBidChangeCallback","onBidBlurCallback","previousPrice","onKeyPress","newValueToSet","GeneralRequirement","OwnerAllow","SubBid","Event","inputElement","tooltipName","useBidderHelpers","getInputElementForBidField","inputType","isLineItem","onKeyDownCallback","valueRequiredClassifications","bidIsUnleveled","isIncludedBidClassification","getClassificationInputFieldCSSClass","classificationToSet","newPrice","currentInputValue","inputValueWithNoCommas","currentNumericInputValue","getCellbackgroundColorForBidClassificationType","bidClassificationType","useBidPackageGrid_Adjustments","bidClassificationTypes","generateSubGrid_AdjustmentsAndBidClassifications","isBidPackageTotalsSection","collapseShouldIncludeAdjustmentsHeaderRow","showTopBorders","currClassificationType","totalsRow","totalsTitle","totalsValue","getLineItems","placement","gridSectionTestId","generateSubGrids_Bidders","currBidder","bidderRows","adjustmentRow","adjustmentBidValue","adjustmentNotes","allowEntryInAdjustmentsRow","customDataAttributes","bidderValue","allLineItemsWithBidForCurrBidder","lineItemBidsTotal","calculateLineItemBidValue","lineItemRollupBidsValue","requirementFulfillmentValues","rf","calculateRequirementFulfillmentBidValue","totalClassificationPrice","totalValue","getTotalValueForBidder","lineItemBidValue","requirementfulfillmentsValue","generateBidPackage_Adjustments_GridSection","adjustmentSubGrid","bidderSubGrids","useBidPackageGrid_Header","generateSubGrid_LineItemsHeader","generateBidPackage_Header_GridSection","lineItemsSubGrid","biddersSubGrids","useHelperHook","getNewInputValue","originalValue","getUpdatableInputElement","sourceObject","isShortInput","onChangeCallback","onBlurCallback","inputFormat","onChangeCallbackFn","updatedObject","onBlurCallbackFn","onKeyDownCallbackFn","pattern","LineItemsDropdownItems","lineItemsEditCallback","lineItemsDeleteCallback","lineItemsAreSelected","setLineItemsAreSelected","useLineItemsHelpers","generateGridRowForLineItem_Details","contextMenuOptions","lineItemEditCallback","lineItemDeleteCallback","setPopoverForQuantityCell","setPopoverForUnitPriceCell","removePopover","mappedOrder","LineItemGridRowSortableContainerId","matchingDropdownOption","unitsOfMeasureDropdownListOptions","lineItemCopy","currOption","data-triggers-popover","getGroupedLineItemRows","lineItemRows","level0Rows","groupedLineItems","currGroupingKey1","currLineItem","newGroupedRow","groupingId","level0Row","groupedLineItems2","level1Rows","currGroupingKey2","level1Row","level1Index","lvl1Rows","isCurrLevel0LastElement","level2Rows","level2Row","level2Index","lvl2Rows","isCurrLevel1LastElement","useBidPackageGrid_LineItems","generateSubGrid_LineItems","currLineItemRow","isSelectedBidder","currLineItemGridRow","currLineItemGridRowIsGroupedRow","lineItem_Value1","lineItem_Value2","lineItem_PlaceholderValue","lineItem_PlaceholderValueFull","matchingRollupBid","matchingLineItem","parentRollupBidExists","currLineItemRowId","lineItemHasPriceOrPlaceholderValue","bidId","generateBidPackage_LineItems_GridSection","AlternateLineItemsHeader","dropdownMenuIconIsDisplayed","setDropdownMenuIconIsDisplayed","lineItemsActionDropdownIsOpen","setLineItemsActionDropdownIsOpen","lineItemMappings","useBidPackageGrid_LineItems_Alternates","generateLineItemsAlternatesGridSectionHeaderRows","headerRow","GlobalCollapseResponseKeyPrefix","data-alternate-name","allLineItemsCount","lineItemsCountLimit","lineItemsCountForSection","secondaryGridRows","rollupBidValue","getLineItemRollupBids","primaryRow","generateLineItemsAlternatesGridSectionHeaderRowExtensions","lineItemsValue","formattedTotalsValue","formattedTotalsFullValue","bidderStatusToClassNameMap","RequestCreated","RequestSent","QuoteReceived","BidderStatusDropdown","options","opt","BidderTrophyIcon","iconText","isSecondBidder","LineItemsDropDownMenu","onDropdownToggle","BiddersDropDownMenu","bidderNameForOpenDropdown","setBidderNameForOpenDropdown","useBidPackageGrid_LineItems_Header","lineItemHeaderRows","lineItemColumnHeaderRow","onBidderStatusChange","bidderSelectTooltip","invalidStatusesForSelectedBidder","bidderHasInvalidStatusForSelectedBidderOrReordering","preventBidderSelection","BidderGridRowSortableContainerId","bidderName","generateBidPackage_LineItems_Header_GridSection","useBidPackageGrid_Requirements","generateSubGrid_Requirements","requirementsCountForType","requirementRows","currRequirement","bidderRequirementRow","matchingFulfillmentObj","requirementFulfillment_PlaceholderValue","requirementCell","requirementHasPriceOrPlaceholderValue","generateBidPackage_Requirements_GridSection","requirementsToDisplay","addArrayItemToBidPackage","entry","arrayPropName","array","arrayClone","Values","castedBidPackage","updateArrayItemInBidPackage","entity","updatedEntity","removeArrayItemFromBidPackage","DataChangeHandlerMap","onUpdate","bidPackageIdOfEntry","onDelete","getLineItemById","setMetadata","metadataId","removeMetadata","bid","rollupBid","adjustmentToDelete","matchingRequirementIndex","requirementFulfillment","updatedRequirementFulfillment","useBidPackage_ChangeNotifications","executeBidPackageChangeHandler","dataEntryType","updatedBidPackage","sortBidders","onChangeCallback_LineItem","currBidPackageCopy","matchingLineItemIndex","onBlurCallback_LineItem","matchingOriginalLineItem","shouldUpdateLineItemQuantity","shouldUpdateLineItemUnitOfMeasure","shouldUpdateLineItemUnitPrice","successFunction_LineItem","setLineItem","errorFunction_LineItem","lineItemToRestore","successFunction_LineItem_Delete","lineItemIdsToDelete","errorFunction_LineItem_Delete","lineItemIdsToRestore","useBidPackage_LineItems","sortAlternates","useProject_ChangeNotifications","setProjectInfo","currentProject","projectClone","alternatesClone","projectChangeHandler","deletedProjectEntry","Deleted","projectName","ChangedBy","reject","Updated","Added","BidPackagePageInternalComponent","isInitialDataLoadComplete","notificationsReceivedDuringInitialDataLoad","setLiveUpdateRegistrationFailed","setProjectId","projectDetailInfo","setProjectDetailInfo","addEditLineItemsFormIsDirty","keyboardShortcutsInfoIsOpen","setKeyboardShortcutsInfoIsOpen","lastEditedBidderForBidderNotes","setLastEditedBidderForBidderNotes","lastEditedAdjustmentForAdjustmentNotes","setLastEditedAdjustmentForAdjustmentNotes","lineItemsModalState","setLineItemsModalState","alternateToAddLineItemsTo","setAlternateToAddLineItemsTo","bidderForDocumentsModal","setBidderForDocumentsModal","autoSaveTimeout","routeParams","useParams","useLocation","signalRBroadcast_Project$","onSignalRBroadcast_Project","signalRBroadcast_BidPackage$","onSignalRBroadcast_BidPackage","setAllBidPackageDropdownOptions","allUnitOfMeasureDropdownOptions","setAllUnitOfMeasureDropdownOptions","setSelectedBidPackageId","selectedBidPackage","setSelectedBidPackage","selectedBidPackage_Staging","selectedBidPackage_Committed","lockedByUser","setLockedByUser","selectedLineItemsMappingsCopy","setLineItemsToEdit","lastFocusedLineItemBidInfo","lastFocusedRequirementFulfillmentBidInfo","lineItemBlurTimeout","requirementFulfillmentBlurTimeout","isProjectAdmin","isUserAssignedContributor","bidPackageIsFrozen","setBidPackageIsFrozen","bidPackageNotesAreFrozen","setBidPackageNotesAreFrozen","bidderNoteIdsThatAreFrozen","setBidderNoteIdsThatAreFrozen","bidderFileUploadContainerIdsThatAreFrozen","setBidderFileUploadIdsThatAreFrozen","adjustmentNoteIdsThatAreFrozen","setAdjustmentNoteIdsThatAreFrozen","projectNotificationHandler","messageAsDataChangedMessage","updatedProjectAdminsMessages","projectAdminsChangedValues","setGridRerenderTriggerObject","typesToCheck","addedBidPackagesDropdownOptions","bidPackageDescription","deletedBidPackageIds","newDropdownOptions","bidPackageNotificationHandler","bidderNoteIds","adjustmentNoteIds","bidderFileUploadContainerIds","bidPackageTotals","dataChangedEntryTypesThatCanAffectTotals","applyBidPackageChanges","runChangeHandlerCompleteCallbacks","onChangeHandlerCompleteCallback","bidPackage2","updatedProject","bidPackageIndex","updateProjectBidPackageCollection","firstBidPackage","currentBidder","previousLineItemsCount","URLSearchParams","search","projectInformation","projectIdFromQueryString","all","bidPackagesData","unitOfMeasureDropdownOptions","bidPackageDropdownOptions","msg","notification","updateLockedByUser","loadProjectDetailInfo","loadBidPackageDetails","bidPackagesObj","bidderNotesPromisesArray","currBidderNoteId","bidderNoteIdsResults","frozenBidderNoteIds","adjustmentNotesPromisesArray","adjustmentNoteIdsResults","frozenAdjustmentNoteIds","bidderFileUploadContainerPromisesArray","currFileUploadContainerId","bidderFileUploadContainerIdsResults","frozenBidderFileUploadContainerIds","basicProjectInfo","lineItemIdsFromBidPackage","sourceIdsForChangeNotifications_CurrValue","currentlyRegisteredSourceIds","sourceIdsForChangeNotifications","newSourceIds","registerForProjectChangeNotifications","sourceIdsToUnregister","batchRegisterForNotifications","registerForBidPackageChangeNotifications","setGridSections","gridSection_Header","setGridSection_Header","gridSection_LineItems_Header","setGridSection_LineItems_Header","gridSections_LineItems","setGridSections_LineItems","gridSection_GeneralRequirements","setGridSection_GeneralRequirements","gridSection_TradeRequirements","setGridSection_TradeRequirements","gridSection_LineItems_Adjustments","setGridSection_LineItems_Adjustments","gridSections_Alternates","setGridSections_Alternates","gridSection_BidPackageTotals","setGridSection_BidPackageTotals","functionToExecute","stagingCopy","committedCopy","currBidPackage","matchingIndex","biddersCopy","onBidderDocumentsModalClose","onBidPackageLockChange","onLineItemsDelete","lineItemsToDelete","lineItemName","allSelectedItems","selectedLineItemIds","selectedLineItems","lineItemsGroupedByAlternateId","dropTargetBidderName","draggedBidderName","draggedBidder","dropTargetBidder","currentOrder","dropTargetOrder","newOrder","targetOrder","newSelectedLineItems","idOfLineItemToEdit","idsOfLineItemsToEdit","idOfLineItemToDelete","idsOfLineItemsToDelete","updateIsDirtyFlag","indexOfLineItemBid","bidsCopy","bidInfo","indexOfRollupBid","indexOfAdjustment","adjustmentData","matchingAdjustment","copy_Staging","copy_Committed","indexOfFulfillment","newSelectedBidderId","updateSelectedBidder","doUnleveledBidsExistForBidder","lineItemsGridSection","getLineItemGroupOrders","numberOfRows","numberOfNewGridSectionsToCreate","ceil","newGridSections","totalsGridSection","alternatesGridSections","currAlternate","gridSectionId1","lineItemsAlternatesGridSection","alternateHeaderRows","alternateHeaderRowExtensions","gridSectionId2","adjustmentsGridSection","newGridSections2","onLineItemsAddedOrEdited","lineItemsCount","updateCommands","onLineItemsDiscard","onLineItemsChange","itemsChanged","onAddEditOnLineItemsModalClosing","onAddEditOnLineItemsDiscard","matchingBidPackage","getBidPackageLockTooltip","currFrozenNoteId","currFrozenFileUploadContainerId","currFrozenAdjustmentNoteId","matchingAlternateName","BidPackagePage","AddEditProjectNotesToProjectCommand","projectNotesId","CloseProjectCommand","AddProjectFeeCommand","DeleteProjectFeeCommand","UpdateProjectFeeCommand","originalName","UpdateProjectFeeOrderCommand","allowedCommands","ProjectFeesBatchCommand","BidSummaryPageContext","BidSummaryPageContextProvider","alternateChange$","alternate_Change","bidAmountBlur$","bidAmount_Blur","bidAmountChange$","bidAmount_Change","contingencyBlur$","contingency_Blur","contingencyChange$","contingency_Change","feesEdit$","fees_Edit","keyboardShortcutsShow$","keyboardShortcuts_Show","feeAmountBlur$","feeAmount_Blur","feeAmountChange$","feeAmount_Change","bidSummaryDisplayOptionsChange$","bidSummary_DisplayOptionsChange","projectClose$","project_Close","projectEditBiddersRanges$","project_EditBiddersRanges","projectEditNotes$","project_EditNotes","projectExportExcel$","project_ExportExcel","projectShowInfo$","project_ShowInfo","feeCalculationRequest$","feeCalculation_Request","useBidSummaryPageContext","BidSummaryKeyboardShortcuts","useFeeTable","projectFees","batchCommand","feeTableFees","setFeeTableFees","feeTableFeesNeedToBeCalculated","setFeeTableFeesNeedToBeCalculated","recalculatingFeeTableFees","newName","newFeeTypeId","newAmount","newReferenceFeeName","feeDtos","calculateFeeTableFees","calculateProjectBidTotal","cf","UpdateProjectBiddersRangesCommand","ProjectBiddersRangesEditForm","formProjectBiddersRanges","projectBiddersRanges","useBidSummary_Settings_ProjectBiddersRangesModal","projectBiddersRangesToEdit","setProjectBiddersRangesToEdit","setIsReadOnly","setCurrentProjectBiddersRangesModalState","newProjectBiddersRangesModalState","onBiddersRangesModalClose","newProjectBiddersRanges","getProjectBiddersRangesModalJSX","SetContingencyOnBidPackageCommand","onChangeCallback_BidAmount","currBidPackages","bidTotalToUpdate","matchingBidTotalIndex","originalBidTotal","newAdjustmentAmount","onBlurCallback_BidAmount","originalBidPackages","currentBidPackages","newBidTotal","onChangeCallback_Contingency","bidPackageContingencyAmount","bidPackageToUpdateIndex","onBlurCallback_Contingency","successFunction_BidAmount","bidPackagesToUpdate","bidPackagesWithUpdatedData","indexOfBidPackageToUpdate","bidPackage_Source","indexOfBidTotalToUpdateFrom","indexOfBidTotalToUpdate","errorFunction_BidAmount","bidPackage_Target_Index","matchingBidTotalFromBidPackageTargetIndex","matchingBidTotalFromBidPackageSource","successFunction_Contingency","errorFunction_Contingency","useBidSummary","useBidSummary_BidPackage_Alternate","bidSummaryOptions","generateBidSummary_BidPackage_Alternate_SubGrid","frozenBidPackageIds","frozenBidPackageAdjustmentNoteIds","displayClassifications","data-alternate-is-enabled","contentRows","dataRows","totalForAllBidPackages","totalAdjustmentAmountsForAllBidPackages","newDataRow","newDataRowTotalCell","bigZero","bidTotalAdjustmentOrZero","bidTotalTotalOrZero","bidTotalContainsAdjustments","cmp","bidPackageAdjustmentNotesAreFrozen","newDataRowAdjustmentCell","subtotalRow","subtotalRowTotalCell","subtotalRowAdjustmentCell","formattedZero","formattedTotalForAllBidPackages","formattedTotalForAllAdjustments","totalContainsAdjustments","useBidSummary_BidPackage_BidAmount","generateBidSummary_BidPackage_BidAmount_SubGrid","emptyRow","totalAdjustments","currBidTotal","newRow","currBidTotalOrZero","currBidAdjustmentAmountOrZero","containsAdjustments","calculatedBaseEstimateAmount","useBidSummary_BidPackage_BidPackages","generateBidSummary_BidPackage_BidPackages_SubGrid","cellWidths","displayAssignedToColumn","columnHeadersRow","bidPackageDescriptionValue","assignedToUserName","emailWithoutDomain","tooltipText","getCellBackgroundColorForClassification","classificationType","Totals","useBidSummary_BidPackage_Classification","generateBidSummary_BidPackage_Classification_SubGrid","columnHeaderRow","classificationTypes","classificationSubtotals","valueForClassification","bidTotalForSelectedBidder","getBidTotalForClassification","newCell","currSubtotalRowCell","useBidSummary_BidPackage_ComparisonToBaseEstimate","generateBidSummary_BidPackage_ComparisonToBaseEstimate_SubGrid","totalAmountForAllBidPackages","totalVarianceForAllBidPackages","selectedBidderBidTotal","variance","calculateVariance","variancePercentage","calculateVariancePercentage","comparisonAmount","useBidSummary_BidPackage_Contingencies","generateBidSummary_BidPackage_Contingencies_SubGrid","totalContingencyAmount","contingencyPercentageCell","formattedcontingencyPercentage","contingencyAmountCell","useBidSummary_BidPackage_Notes","generateBidSummary_BidPackage_Notes_SubGrid","useBidSummary_BidPackage_SecondBidderAnalysis","getSecondBidderAndTotal","bidderTotals","secondBidder","generateBidSummary_BidPackage_SecondBidderAnalysis_SubGrid","selectedBidderTotal","secondBidderInfo","secondaryBidValue","useBidSummary_BidPackage_Totals","generateBidSummary_BidPackage_Totals_SubGrid","projectPreferences","data-blah","getCellBackgroundColor","numberOfBids","subtotalForAllTotals","currBidPackageTotal","calculateBidTotal","data-number-of-bids-color","useBidSummary_Fees_Alternate","generateBidSummary_Fees_Alternate_SubGrid","projectHasFeeCalculationFailure","padForClassificationsSpacing","currFeeValue","calculatedValues","currFeeIsOrReferencesLumpSum","newDataCell","useBidSummary_Fees_Alternate_Placeholder","generateBidSummary_Fees_Alternate_Placeholder_SubGrid","useBidSummary_Fees_BidAmount","generateBidSummary_Fees_BidAmount_SubGrid","useBidSummary_Fees_Classifications","generateBidSummary_Fees_Classifications_SubGrid","useBidSummary_Fees_Contingencies","generateBidSummary_Fees_Contingencies_SubGrid","FeeCalculationFailureNotification","retryButtonClicked","setRetryButtonClicked","onRetryClick","useBidSummary_Fees_Fees","generateBidSummary_Fees_Fees_SubGrid","isProjectContributor","isProjectFrozen","feeTypeLabel","feeName","useBidSummary_Fees_Totals","generateBidSummary_Fees_Totals_SubGrid","padForNotesSectionSpacing","currFeeTotal","bidPackageGridSection_TestId","feesGridSection_TestId","useBidSummaryGrid","subGrid_BidPackage_BidPackages","setSubGrid_BidPackages","subGrid_BidPackage_BidAmount","setSubGrid_BidAmount","subGrids_BidPackage_Alternates","setSubGrids_BidPackage_Alternates","subGrid_BidPackage_Contingencies","setSubGrid_BidPackage_Contingencies","subGrid_BidPackage_Totals","setSubGrid_BidPackage_Totals","subGrid_BidPackage_Classification","setSubGrid_BidPackage_Classification","subGrid_BidPackage_SecondBidderAnalysis","setSubGrid_BidPackage_SecondBidderAnalysis","subGrid_BidPackage_ComparisonToBaseEstimate","setSubGrid_BidPackage_ComparisonToBaseEstimate","subGrid_BidPackage_Notes","setSubGrid_BidPackage_Notes","subGrid_Fees_Classifications","setSubGrid_Fees_Classifications","subGrid_Fees_Fees","setSubGrid_Fees_Fees","subGrid_Fees_BidAmount","setSubGrid_Fees_BidAmount","subGrids_Fees_Alternates","setSubGrids_Fees_Alternates","subGrid_Fees_Contingencies","setSubGrid_Fees_Contingencies","subGrid_Fees_Totals","setSubGrid_Fees_Totals","generateSummaryGridSections","bidPackagesSecondarySubGrids","displayAnalysis","displayNotes","feesSecondarySubGrids","alternateSubGrids","placeholderTestId","subGrids","useBidSummaryPageHeader","generateBidSummaryPageHeader","pageIsScrolled","projectSettingsAreFrozen","projectHasNotes","UpdateProjectAlternateEnabledStateCommand","onChangeCallback_Alternate","alternateCollection","alternateNameToUpdate","copiedCollection","existingIndex","clonedAlternate","createAlternateUpdateCommand","successFunction_Alternate","alternateCollectionToUpdate","alternateCollectionWithUpdatedData","foundAlternate","errorFunction_Alternate","useBidSummary_Alternates","updateBidPackageTotals","updatedBidPackageTotals","updatedBidTotal","matchingBidTotal","updateEntryValuesWithAssignedUserObject","currEntry","assignedUser","useBidSummary_ChangeNotifications","updateEntity","entityToUpdate","updateEntityInArray","currentArrayValue","removeEntityFromArray","upsertEntityInArray","arrayToAddTo","newEntity","indexOfExistingEntity","getDataChangeHandlerMap","updateBidPackageChildEntity","updater","projectIdOfEntry","cloneOfBidders","feesToUpdate","feeIndex","cloneOfFeeCalculatedValues","addFeesFn","feeCalculatedValueId","feeCalculatedValueIndex","updatedCalculatedValues","updateFeesFn","deleteFeesFn","bidPackageChangeHandler","feesTableKey","setFeesTableKey","setBidSummaryOptions","setIsInitialDataLoadComplete","setBidPackages","bidPackages_Staging","bidPackages_Committed","setAlternates","alternates_Staging","alternates_Committed","setProjectFees","setProjectPreferences","notesModalIsOpen","setNotesModalIsOpen","feesModalIsOpen","setFeesModalIsOpen","alternatesToUpdateFromSignalRHandler","bidPackagesToUpdateFromSignalRHandler","detailProjectInfoToUpdateFromSignalRHandler","feesToUpdateFromSignalRHandler","projectFees_Committed","projectIsFrozen","setProjectIsFrozen","projectNotesAreFrozen","setProjectNotesAreFrozen","bidPackageIdsThatAreFrozen","setBidPackageIdsThatAreFrozen","bidSummaryPageHeader","setBidSummaryPageHeader","projectIsClosed","bidPackageIdsForChangeNotifications_CurrValue","currentlyRegisteredBidPackageSourceIds","bidPackageIdsForChangeNotifications","bidPackageNoteIds","bidPackageAdjustmentNoteIds","idsToRegisterForNotifications","projectIdsForChangeNotifications_CurrValue","currentlyRegisteredProjectSourceIds","projectIdsForChangeNotifications","idsToWatch","onProjectBiddersRangesSubmitClick","saveProjectNotes","onNotesClose","sanitizedNotes","onNotesModalClose","downloadProjectExport","messagesWithAssignedToUserIdChange","usersArray","results","updatedBidPackages","updatedProjectInfo","updatedAlternates","updatedProjectFees","updateBidPackagesContingencyAmount","dataChangeEntryTypesThatCanAffectGrid","updatedPreferences","BidSummaryApi","updatedBidPackages_Staging","updatedBidPackages_Committed","bidPackageIdsThatAffectContingency","systemSettingsNotificationHandler","bidPackagesPromisesArray","bidPackagesFrozenResults","bidPackageAdjustmentNoteIdsPromisesArray","bidPackageAdjustmentNotesFrozenResults","newProjectFees","updateBidTotalsIsDirtyFlag","matchingBidPackageIndex","newBidTotalObj","newBidSummaryOptions","originalDisplayAssignedToValue","feeAndAmount","updateFeeAmount","feeToUpdate","originalFeeAmount","updateFees","matchingFeeIndex","summaryGridSections","currFrozenNotesId","k","BidSummaryPage","CreateProjectCommand","information","bidPackagesToInclude","bidPackageAssignments","generalRequirementsToInclude","feesToInclude","permissions","UpdateProjectCommand","bidPackagesToExclude","generalRequirementsToExclude","alternatesToUpdate","alternatesToAdd","alternatesToDelete","feesToExclude","navigateBack","goBack","getErrorMessagesById","ProjectErrorDisplay","errorId","errorsToDisplay","AddEditAlternates","updateAlternates","newAlternate","setNewAlternate","alternateInputRef","deleteAlternate","hasLineItems","BTCheckBox","containerClassNames","orientation","AddEditBidPackages","updateBidPackages","userOptions","lodash","isDupe","newBidPackage","targetBidPackage","AddEditFees","targetFee","renderFeeValue","feeTypeName","AddEditGeneralRequirements","generalRequirements","updateGeneralRequirements","newGeneralRequirement","gr","targetRequirement","BTMultiSelect","filteredData","setFilteredData","filterable","onFilterChange","filterBy","getFilteredData","AddEditPermissions","updatePermissions","generateUserOptionsByRole","projectAdminOptions","contributorOptions","opts","admin","updatedPermissions","BTDatePicker","AddEditProjectInformation","userCanEditImage","updateProjectInformation","imageUrl","setImageUrl","unitOfMeasureOptions","file","getRawFile","addEditProjectReducer","emptySiteAddress","emptyProjectInformation","ProjectPage","setProject","newProjectId","projectNames","setProjectNames","projectToEdit","setProjectToEdit","setIsNew","isProcessing","setIsProcessing","projectInformationRef","projectUploadContainerIdIsFrozen","setProjectUploadContainerIdIsFrozen","isBidPackagesAreaOpen","setIsBidPackagesAreaOpen","isGeneralRequirementsAreaOpen","setIsGeneralRequirementsAreaOpen","isAlternatesAreaOpen","setIsAlternatesAreaOpen","isFeesAreaOpen","setIsFeesAreaOpen","isPermissionsAreaOpen","setIsPermissionsAreaOpen","isLoaded","setIsLoaded","duplicateAlternateError","emptyAlternateError","projectNameRequiredError","oneBidPackageRequiredError","projectDateError","projectBidDueDateError","projectImageTypeError","projectImageSizeError","unitOfMeasureWithoutTotalBuildingAreaError","unitOfMeasureWithoutTotalSiteAreaError","informationChanged","bidPackagesChanged","generalRequirementsChanged","alternatesChanged","feesChanged","permissionsChanged","basicProjectData","unitOfMeasureData","generalConditionsData","bidPackageData","generalRequirementData","feeData","bpd","projectData","allBasicProjectInfoData","allUnitOfMeasureData","allGeneralConditionData","allBidPackageData","allGeneralRequirementData","allFeeData","allUserData","currentProjectDetailedInfo","currentProjectBidPackagesCollection","currentProjectAlternatesCollection","currentProjectFeesCollection","bidPackageIdsPromisesArray","bidPackageIdsResults","fileUploadContainerIdResult","currentProjectBidPackages","bidPackageUser","pbp","currentProjectGRs","bpr","cgr","currentProjectGeneralRequirements","currentProjectFees","fd","currentProjectAdmins","currentContributors","currentProjectPermissions","sortedAlternates","projectIdForRedirect","projectAndBidPackageIds","validateProjectInformation","cleanedUpName","validatePermissions","newPermissions","previousPermissions","projectAdminsToRemove","contributorsToRemove","assignedUserToBidPackageMap","addErrorIfUserIsAssignedToBidPackage","userToRemove","bpCodes","bidPackageCodes","validateBidPackages","duplicateSelectedBidPackages","bp2","index2","codes","shouldUpdateContributors","updatedContributors","newContributors","uc","up","userContributor","currUser","userName","updatedGeneralRequirements","validateFees","feesIncludedButMissingReferencedFee","fee2","duplicateSelectedFees","validateAlternates","processFile","reader","FileReader","onload","onerror","readAsDataURL","saveChanges","processedFile","fileData","subTitle","imageData","imageName","bpa","updatedInfo","previousAddress","updatedAddress","siteAddressUpdates","previousBidPackage","prev","updatedProjectAlternate","originalAlternate","alternateWithUpdate","updatedAlternateName","updatedAlternate","navigateAway","getFileNameWithoutExtension","importAll","requireContext","translations","TranslationFilesMap","require","useVersionCheck","versionCheckTimeout","checkVersion","getTime","versionData","text2","allowEscapeKey","didUserGetNewestVersionAfterBeingPrompted","useScript","scriptElement","addScriptToPage","script","createElement","async","walkMeScriptUrl","useWalkMe","walkMeScriptUrlToUse","initializeWalkMeScript","_walkmeConfig","smartLoad","setWalkMeUserInfo","identifier","userIdentifier","isAdmin","isContributor","logLevelLog","RM","library","faArrowDown","faArrowUp","faBars","faBuilding","faChartBar","faCheck","faCheckCircle","faCheckSquare","faChevronDown","faCircle","faCog","faColumns","faCopy","faDatabase","faDollarSign","faEdit","faEllipsisV","faEnvelope","faExclamationTriangle","faFileAlt","faFileExcel","faFileImage","faFilePdf","faFileWord","faGripHorizontal","faHeadset","faInfoCircle","faKeyboard","faList","faLock","faLockOpen","faMinusSquare","faPaste","faPhoneAlt","faPlus","faPlusSquare","faSearch","faSlash","faSortAmountDownAlt","faSortAmountUpAlt","faSpinner","faSquare","faStickyNote","faTh","faTimes","faTrash","faTrophy","faUser","faUsers","faWifi","faWindowMaximize","faWindowMinimize","faWindowRestore","farFileArchive","farSquare","App","locale","setLocale","onLanguageChanged","lang","i18n","lastLocationValue","lastValue_ScrollX","lastValue_ScrollY","lastValue_WindowSize","allInitialDataIsLoaded","setAllInitialDataIsLoaded","shouldRedirectUnlicensedUser","setShouldRedirectUnlicensedUser","envName","handleSSOErrors","getLastError","clearLastError","handleSSOPasswordResetLogic","ssoPasswordResetStatus","getPasswordResetStatus","pathname","urlContainsSSOHash","userIsLoggedIn","login","loadClientsAndShowOverlay","clientOrganizations","client","onCancelClick","onClientSelected","clientOrgId","errorObj","userEmailAddress","userIsContributor","loadSystemSettings","useBeforeunload","disconnect","scrollEventTimer","scrollEventHandler","resizeEventTimer","innerHeight","innerWidth","exact","path","ConfirmationOverlay","firstButtonRef","lastButtonRef","confirmationOverlayDisplayInfo","setConfirmationOverlayDisplayInfo","loadingPageOverlayCssClasses","activeElement","onTab","currButton","checkIfLastItem","balloonsLetters","EEBalloons","balloonsAreDisplayed","setBalloonsAreDisplayed","displayBalloons","FloatingLoadingIndicator","floatingLoadingIndicatorDisplayInfo_Blue","setFloatingLoadingIndicatorDisplayInfo_Blue","floatingLoadingIndicatorDisplayInfo_Green","setFloatingLoadingIndicatorDisplayInfo_Green","counter_Blue","counter_Green","LoadingIndicator","LoadingPageOverlay","loadingOverlayCounter","MobileDeviceOverlay","overrideWarning","setOverrideWarning","setBodyCSSClass","displayOverride","matchMedia","NotificationPanel","queuedNotificationsCopy","notificationBeingDisplayed","setNotificationBeingDisplayed","notificationBeingDisplayedCopy","setIsDisplayed","hideCurrentNotificationTimeoutPromise","notificationTimeout","testTimeout","showNextNotification","nextNotification","cssClassesArray","BTPopover","displayedPopoverInfoCopy","setDisplayedPopoverInfoCopy","hidePopoverTimeout","newInfo","Popover","fade","onMouseOut","PopoverBody","onMouseOver","ReloadAppTimer","timeRemaining","setTimeRemaining","reloadPage","counterTimeout","decrementCounter","secondsRemaining","getSecondsString","SupportOverlay","supportOverlayDisplayInfo","setSupportOverlayDisplayInfo","selectedClient","setSelectedClient","defaultClientOrgId","selectedClientChangeHandler","load","weekData","frCaGeneric","frCaGregorian","frCaDateFields","frCaTimeZoneNames","initReactI18next","resources","getTranslationsFunc","translationFile","getInitialTranslations","lng","interpolation","escapeValue","toLocaleString","Boolean","hostname","baseUrl","getElementsByTagName","rootElement","getElementById","instrumentationKey","browserHistory","createBrowserHistory","basename","reactPlugin","ReactPlugin","appInsights","ApplicationInsights","distributedTracingMode","DistributedTracingModes","W3C","enableCorsCorrelation","enableAutoRouteTracking","extensions","extensionConfig","loadAppInsights","addTelemetryInitializer","envelope","tags","addDependencyListener","details","traceId","Util","generateW3CId","initializeAppInsights","ReactDOM","render","serviceWorker","ready","registration","unregister"],"mappings":"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","file":"static/js/main.d8ac873a.chunk.js","sourcesContent":["module.exports = __webpack_public_path__ + \"static/media/default-project-image.7590b9d1.png\";","module.exports = __webpack_public_path__ + \"static/media/error.406d70ca.svg\";","module.exports = __webpack_public_path__ + \"static/media/exclamation.4e0bb1a4.svg\";","module.exports = __webpack_public_path__ + \"static/media/stop.a94a5955.svg\";","module.exports = __webpack_public_path__ + \"static/media/snowflake.b1e2d5c6.svg\";","var map = {\n\t\"./bid-package-maintenance.json\": 423,\n\t\"./bid-package.json\": 424,\n\t\"./bid-summary.json\": 425,\n\t\"./errors.json\": 426,\n\t\"./fees.json\": 427,\n\t\"./frozen-entities.json\": 428,\n\t\"./general-conditions.json\": 429,\n\t\"./general-requirements.json\": 430,\n\t\"./general.json\": 431,\n\t\"./home.json\": 432,\n\t\"./navigation.json\": 433,\n\t\"./preferences.json\": 434,\n\t\"./project.json\": 435,\n\t\"./sample-data.json\": 436,\n\t\"./units-of-measure.json\": 437,\n\t\"./user-permissions.json\": 438\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 422;","var map = {\n\t\"./bid-package-maintenance.json\": 440,\n\t\"./bid-summary.json\": 441,\n\t\"./general-requirements.json\": 442,\n\t\"./general.json\": 443,\n\t\"./navigation.json\": 444,\n\t\"./preferences.json\": 445,\n\t\"./units-of-measure.json\": 446,\n\t\"./user-permissions.json\": 447\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 439;","import { useCallback, useRef } from 'react';\r\nimport { BehaviorSubject, Observable, Subject } from 'rxjs';\r\n\r\nconst useObservable = function (): [Observable, () => void] {\r\n const _subject = useRef>(new Subject());\r\n const observable$ = useRef>(_subject.current.asObservable());\r\n\r\n const updateObservableValue = useCallback(() => {\r\n _subject.current.next();\r\n }, []);\r\n\r\n return [observable$.current, updateObservableValue];\r\n};\r\n\r\n// Creates an observable that is backed by a Subject.\r\n// NOTE: When the observable is subscribed to, it will NOT broadcast its current value like a behavior subject will.\r\nconst useObservableWithValue = function (): [Observable, (value: T) => void] {\r\n const _subject = useRef>(new Subject());\r\n const observable$ = useRef>(_subject.current.asObservable());\r\n\r\n const updateObservableValue = useCallback((newValue: T) => {\r\n _subject.current.next(newValue);\r\n }, []);\r\n\r\n return [observable$.current, updateObservableValue];\r\n};\r\n\r\n// Creates an observable that is backed by a BehaviorSubject, which will broadcast its current value\r\n// when it is subscribed to (regular subjects do NOT do this upon subscription)\r\nconst useObservableWithBehaviorSubject = function (\r\n initialValue: T,\r\n): [Observable, (value: T) => void] {\r\n const _behaviorSubject = useRef>(new BehaviorSubject(initialValue));\r\n const observable$ = useRef>(_behaviorSubject.current.asObservable());\r\n\r\n const updateObservableValue = useCallback((newValue: T) => {\r\n _behaviorSubject.current.next(newValue);\r\n }, []);\r\n\r\n return [observable$.current, updateObservableValue];\r\n};\r\n\r\nexport { useObservable, useObservableWithValue, useObservableWithBehaviorSubject };\r\n","import React, { useRef, useState } from 'react';\r\nimport { Observable } from 'rxjs';\r\nimport { useObservable, useObservableWithValue } from '../../../hooks/observables/useObservable';\r\n\r\ninterface SystemSettings {\r\n generalConditionsCode: string | null;\r\n canLoadSampleData: boolean;\r\n}\r\n\r\nexport interface WindowDimensions {\r\n height: number;\r\n width: number;\r\n}\r\n\r\ninterface BTGeneralContextInterface {\r\n // Ref variables\r\n signalRResponseTimeout: React.MutableRefObject;\r\n\r\n // State variables\r\n easterEgg_BoogieNights: boolean;\r\n systemSettings: SystemSettings | undefined;\r\n\r\n // Observables\r\n appWillRestart$: Observable;\r\n pageScroll_X$: Observable;\r\n pageScroll_Y$: Observable;\r\n windowResize$: Observable;\r\n userJustGotTheLatestUpdate$: Observable;\r\n\r\n // State setter functions\r\n setEasterEgg_BoogieNights: React.Dispatch>;\r\n setSystemSettings: React.Dispatch>;\r\n\r\n // Observable trigger functions\r\n onAppWillRestart: () => void;\r\n onUserJustGotTheLatestUpdate: () => void;\r\n setPageScroll_X: (offset: number) => void;\r\n setPageScroll_Y: (offset: number) => void;\r\n setWindowResize: (dimensions: WindowDimensions) => void;\r\n}\r\n\r\nconst BTGeneralContext = React.createContext(\r\n {} as BTGeneralContextInterface,\r\n);\r\n\r\nconst BTGeneralContextProvider: React.FC = (props) => {\r\n const [systemSettings, setSystemSettings] = useState();\r\n\r\n const [userJustGotTheLatestUpdate$, onUserJustGotTheLatestUpdate] = useObservable();\r\n\r\n const [appWillRestart$, onAppWillRestart] = useObservable();\r\n\r\n // Used in places where we rely on SignalR to know when a command completed, but have a timeout\r\n // function just in case we never get the SignalR notification\r\n const signalRResponseTimeout = useRef(null);\r\n\r\n // NOTE: We use observables to broadcast the page offset to interested parties, for performance reasons.\r\n // If this is a state variable, any component that takes a dependency on it will re-render with every\r\n // scroll action the user took, but as an observable, only components that subscribe to the observable will\r\n // react to it in the subscription callback and re-render if needed.\r\n const [pageScroll_X$, setPageScroll_X] = useObservableWithValue();\r\n const [pageScroll_Y$, setPageScroll_Y] = useObservableWithValue();\r\n\r\n const [windowResize$, setWindowResize] = useObservableWithValue();\r\n\r\n const [easterEgg_BoogieNights, setEasterEgg_BoogieNights] = useState(false);\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport { BTGeneralContext, BTGeneralContextProvider };\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { nameof } from '../../utils/nameof';\r\n\r\nexport abstract class CommandBase implements ICommand {\r\n public readonly __type: string;\r\n public readonly apiUrl: string;\r\n public readonly httpMethod: HttpMethods;\r\n\r\n constructor(type: string, apiUrl: string, httpMethod: HttpMethods) {\r\n this.__type = type;\r\n this.apiUrl = apiUrl;\r\n this.httpMethod = httpMethod;\r\n }\r\n\r\n // This is meant to be overridden as needed but will return the properties of this object (minus a few) by default\r\n public generateRequestData(): unknown {\r\n // NOTE: We output the \"__type\" property so code consuming this can choose what to do with it, but these other properties get excluded\r\n const propertiesToIgnore: string[] = [\r\n nameof('apiUrl'),\r\n nameof('httpMethod'),\r\n ];\r\n\r\n const returnValue: any = {};\r\n const thisAsAny = this as any;\r\n\r\n const propertiesToExport: any[] = Object.getOwnPropertyNames(this).filter(\r\n (v) => !propertiesToIgnore.includes(v),\r\n );\r\n\r\n propertiesToExport.forEach((currKey) => {\r\n returnValue[currKey] = thisAsAny[currKey];\r\n });\r\n\r\n return returnValue;\r\n }\r\n}\r\n","import { CommandBase } from '../CommandBase';\n\nexport class UpdateCanLoadSampleDataCommand extends CommandBase {\n constructor(public value: boolean) {\n super(\n 'DESTINI.BidDay.Commands.Application.UpdateCanLoadSampleData',\n 'sample-data/update-can-load-sample-data',\n 'post',\n );\n }\n}\n","const PRODUCT_NAME = 'Bid Day';\r\nconst PRODUCT_NAME_FULL = `DESTINI ${PRODUCT_NAME}`;\r\n\r\n// NOTE: We provide string constants to match the \"event.key\" property, since the \"event.which\" and\r\n// \"event.keyCode\" properties that provide number representations are deprecated.\r\nconst KEY_A = 'A';\r\nconst KEY_B = 'B';\r\nconst KEY_C = 'C';\r\nconst KEY_G = 'G';\r\nconst KEY_I = 'I';\r\nconst KEY_M = 'M';\r\nconst KEY_N = 'N';\r\nconst KEY_O = 'O';\r\nconst KEY_R = 'R';\r\nconst KEY_S = 'S';\r\nconst KEY_V = 'V';\r\nconst KEY_X = 'X';\r\nconst KEY_Z = 'Z';\r\n\r\nconst KEY_ARROW_DOWN = 'ArrowDown';\r\nconst KEY_ARROW_LEFT = 'ArrowLeft';\r\nconst KEY_ARROW_RIGHT = 'ArrowRight';\r\nconst KEY_ARROW_UP = 'ArrowUp';\r\nconst KEY_BACKSPACE = 'Backspace';\r\nconst KEY_DELETE = 'Delete';\r\nconst KEY_ENTER = 'Enter';\r\nconst KEY_ESCAPE = 'Escape';\r\nconst KEY_HYPHEN = '-';\r\nconst KEY_PERIOD = '.';\r\nconst KEY_SPACE = ' ';\r\nconst KEY_TAB = 'Tab';\r\n\r\n// These correspond to the Big.Js rounding modes\r\nconst ROUNDING_MODE = {\r\n TRUNCATE: 0, // No rounding\r\n ROUND_HALF_UP: 1, // Rounds towards nearest neighbor. If equidistant, rounds away from zero.\r\n};\r\n\r\n// These values support the precision accuracy of decimals displayed through the BTNumericInput and Kendo numeric components\r\nconst DECIMAL_PRECISION_FORMAT = {\r\n MINIMUM_FRACTION_DIGITS: 2,\r\n MAXIMUM_FRACTION_DIGITS: 5,\r\n};\r\n\r\n// These entity ID's correspond to particular domain entity ID's that we hard code, for things like system settings\r\nconst ENTITY_IDS = {\r\n SYSTEM_SETTINGS: '67DF4523-E178-4B7A-B9C8-131BA8763206',\r\n BID_DAY_APPLICATION: 'B8EF5485-553D-40D2-B7D7-11233EDC936E',\r\n};\r\n\r\nconst EMPTY_FULL_PRECISION = '0.00000';\r\n\r\n// These values support the precision accuracy of percentages displayed through the BTNumericInput as well as through the utility method FormatNumberAsPercentage\r\nconst PERCENT_MINIMUM_FRACTION_DIGITS = 0;\r\nconst PERCENT_MAXIMUM_FRACTION_DIGITS = 5;\r\n\r\nconst SIGNALR_WAIT_TIMEOUT = 180_000;\r\n\r\n// The base z-index value to use throughout the UI.\r\n// NOTE: this value MUST match what's in 'src\\DESTINI.BidDay.Web\\ClientApp\\src\\styles\\common-variables.scss'\r\nconst UI_ZINDEXBASE = 20000;\r\n\r\nconst GeneralConstants = {\r\n ENTITY_IDS,\r\n\r\n PRODUCT_NAME,\r\n PRODUCT_NAME_FULL,\r\n\r\n KEY_A,\r\n KEY_B,\r\n KEY_C,\r\n KEY_G,\r\n KEY_I,\r\n KEY_M,\r\n KEY_N,\r\n KEY_O,\r\n KEY_R,\r\n KEY_S,\r\n KEY_V,\r\n KEY_X,\r\n KEY_Z,\r\n\r\n KEY_ARROW_DOWN,\r\n KEY_ARROW_LEFT,\r\n KEY_ARROW_RIGHT,\r\n KEY_ARROW_UP,\r\n KEY_BACKSPACE,\r\n KEY_DELETE,\r\n KEY_ENTER,\r\n KEY_ESCAPE,\r\n KEY_HYPHEN,\r\n KEY_PERIOD,\r\n KEY_SPACE,\r\n KEY_TAB,\r\n\r\n ROUNDING_MODE,\r\n DECIMAL_PRECISION_FORMAT,\r\n EMPTY_FULL_PRECISION,\r\n\r\n PERCENT_MINIMUM_FRACTION_DIGITS,\r\n PERCENT_MAXIMUM_FRACTION_DIGITS,\r\n\r\n SIGNALR_WAIT_TIMEOUT,\r\n\r\n UI_ZINDEXBASE,\r\n};\r\n\r\nexport default GeneralConstants;\r\n","// NOTE: When creating 'full' routes, we use an empty string as the first element in the array we are concatenating so we get a leading forward slash\nconst AdminRoutes = {\n FROZEN_ENTITIES: ['', 'admin', 'frozen-entities'].join('/'),\n};\n\nexport default AdminRoutes;\n","export class BidPackageLineItemDefinition implements IODataResource {\r\n public readonly oDataResourceName = 'BidPackageLineItemDefinition';\r\n\r\n public id!: string;\r\n public bidPackageDefinitionId!: string;\r\n public index!: number;\r\n public description!: string;\r\n public unitOfMeasure!: string;\r\n}\r\n","export class TradeRequirementDefinition implements IODataResource {\r\n public readonly oDataResourceName = 'TradeRequirementDefinition';\r\n\r\n public id: string | undefined;\r\n public index: number | undefined;\r\n public description: string | undefined;\r\n public requirementFulfillmentType: number | undefined;\r\n public bidPackageCode: string | undefined;\r\n}\r\n","import { Type } from 'class-transformer';\r\nimport { BidPackageLineItemDefinition } from './bid-package-line-item-definition';\r\nimport { TradeRequirementDefinition } from './trade-requirement-definition';\r\n\r\nexport class BidPackageDefinition implements IODataResource {\r\n public readonly oDataResourceName = 'BidPackageDefinition';\r\n\r\n public id!: string;\r\n public code!: string;\r\n public description!: string;\r\n\r\n @Type(() => TradeRequirementDefinition)\r\n public tradeRequirementDefinitions: TradeRequirementDefinition[] = [];\r\n\r\n @Type(() => BidPackageLineItemDefinition)\r\n public lineItemDefinitions: BidPackageLineItemDefinition[] = [];\r\n}\r\n","const SystemValues = {\r\n DOMAINS: 'Domains',\r\n GENERAL_CONDITIONS_CODE: 'GeneralConditionsCode',\r\n CAN_LOAD_SAMPLE_DATA: 'CanLoadSampleData',\r\n};\r\n\r\nexport default SystemValues;\r\n","// https://stackoverflow.com/a/2117523\r\nconst uuidv4 = (): string => {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return (([1e7] as any) + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c: any) =>\r\n (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16),\r\n );\r\n};\r\n\r\nconst generateUuid = (): string => uuidv4();\r\n\r\nconst isValidUuid = (uuid: string): boolean => {\r\n const regex = new RegExp(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$/i);\r\n return regex.test(uuid);\r\n};\r\n\r\nconst emptyUuid = '00000000-0000-0000-0000-000000000000';\r\n\r\nexport { generateUuid, isValidUuid, emptyUuid };\r\n","import moment from 'moment';\r\nimport { isValidUuid } from '../../utils/uuid';\r\n\r\n// NOTE: We use these and translate them into OData strings later so it's easier to read\r\ntype ODataQueryFilterTypes =\r\n | 'equals'\r\n | 'not equals'\r\n | 'less than'\r\n | 'less than or equal to'\r\n | 'greater than'\r\n | 'greater than or equal to'\r\n | 'any'\r\n | 'all';\r\n\r\nexport interface ODataQuery {\r\n oDataClass: Ctor | null;\r\n expandedQueries: ExpandedODataQuery[];\r\n selectors: string[];\r\n filters: ODataQueryFilter[];\r\n useCount: boolean;\r\n top: number | null;\r\n}\r\n\r\ninterface ExpandedODataQuery extends ODataQuery {\r\n propertyName: string;\r\n}\r\n\r\nexport interface ODataQueryFilter {\r\n type: ODataQueryFilterTypes;\r\n propertyName: string;\r\n value: string | number | boolean | Date | ODataQueryFilter | null;\r\n}\r\n\r\ninterface ODataUrlPart {\r\n propertyName: string | null;\r\n expandedODataUrlParts: ODataUrlPart[];\r\n filtersStringParts: string[];\r\n useCount: boolean; // A value we can provide that will provide the count of returned values alongside the data\r\n top: number | null; // A value we can provide to limit the results returned\r\n selectorsStringParts: string[];\r\n}\r\n\r\nexport class BTODataService {\r\n private static getODataFilterOperator(type: ODataQueryFilterTypes): string {\r\n switch (type) {\r\n case 'equals':\r\n return 'eq';\r\n\r\n case 'not equals':\r\n return 'ne';\r\n\r\n case 'greater than':\r\n return 'gt';\r\n\r\n case 'greater than or equal to':\r\n return 'ge';\r\n\r\n case 'less than':\r\n return 'lt';\r\n\r\n case 'less than or equal to':\r\n return 'le';\r\n\r\n default:\r\n throw new Error(`Unsupported OData filter operator: ${type}`);\r\n }\r\n }\r\n\r\n // Generates a URL part object for an OData query\r\n private static generateODataUrlPart(query: ODataQuery | ExpandedODataQuery): ODataUrlPart {\r\n const returnValue: ODataUrlPart = {\r\n propertyName: (query as ExpandedODataQuery).propertyName || null,\r\n expandedODataUrlParts: [],\r\n filtersStringParts: [],\r\n selectorsStringParts: [],\r\n useCount: false,\r\n top: null,\r\n };\r\n\r\n if (query?.filters?.length) {\r\n query.filters.forEach((currFilter) => {\r\n const generateFilterStringPart = (queryFilter: ODataQueryFilter): string => {\r\n const oDataOperatorString = this.getODataFilterOperator(queryFilter.type);\r\n\r\n // String\r\n if (typeof queryFilter.value === 'string') {\r\n const valueIsUuid = isValidUuid(queryFilter.value as string);\r\n return `${queryFilter.propertyName} ${oDataOperatorString} ${!valueIsUuid ? \"'\" : ''}${\r\n queryFilter.value\r\n }${!valueIsUuid ? \"'\" : ''}`;\r\n }\r\n // Number\r\n else if (typeof queryFilter.value === 'number') {\r\n return `${queryFilter.propertyName} ${oDataOperatorString} ${queryFilter.value}`;\r\n }\r\n // Boolean\r\n else if (typeof queryFilter.value === 'boolean') {\r\n return `${queryFilter.propertyName} ${oDataOperatorString} ${queryFilter.value}`;\r\n }\r\n // Date\r\n else if (queryFilter.value instanceof Date) {\r\n return `${queryFilter.propertyName} ${oDataOperatorString} ${moment(\r\n queryFilter.value,\r\n ).toISOString()}`;\r\n }\r\n // Null\r\n else if (queryFilter.value === null) {\r\n return `${queryFilter.propertyName} ${oDataOperatorString} null`;\r\n }\r\n\r\n throw new Error(`Invalid query filter value: ${queryFilter.value}`);\r\n };\r\n\r\n // For 'any' / 'all' queries, we do a nested filter operation on the property name specified\r\n if (currFilter.type === 'any' || currFilter.type === 'all') {\r\n const valueAsQuery = currFilter.value as ODataQueryFilter;\r\n returnValue.filtersStringParts.push(\r\n `${currFilter.propertyName}/${currFilter.type}(x:x/${generateFilterStringPart(\r\n valueAsQuery,\r\n )})`,\r\n );\r\n } else {\r\n returnValue.filtersStringParts.push(generateFilterStringPart(currFilter));\r\n }\r\n });\r\n }\r\n\r\n if (query?.selectors?.length) {\r\n query.selectors.forEach((currSelectorPropertyName) => {\r\n returnValue.selectorsStringParts.push(currSelectorPropertyName);\r\n });\r\n }\r\n\r\n if (query?.useCount) {\r\n returnValue.useCount = true;\r\n }\r\n\r\n if (query?.top !== null) {\r\n returnValue.top = query.top;\r\n }\r\n\r\n if (query?.expandedQueries?.length) {\r\n query.expandedQueries.forEach((currQuery) => {\r\n returnValue.expandedODataUrlParts.push(this.generateODataUrlPart(currQuery));\r\n });\r\n }\r\n\r\n return returnValue;\r\n }\r\n\r\n // Generates an OData URL string (select / filter / expand parts)\r\n private static generateODataUrlStringFragments(odataUrlPart: ODataUrlPart): string {\r\n let returnValue = odataUrlPart.propertyName || '';\r\n\r\n // NOTE: Right now, all filter clauses are joined with \"and\" but we can expand this in the future to allow more flexibility\r\n const filtersString = odataUrlPart.filtersStringParts.length\r\n ? `$filter=${odataUrlPart.filtersStringParts.join(' and ')}`\r\n : '';\r\n\r\n // NOTE: Right now, this doesn't support nested objects (ex. $select=user.address.city)\r\n const selectorsString = odataUrlPart.selectorsStringParts.length\r\n ? `$select=${odataUrlPart.selectorsStringParts.join(',')}`\r\n : '';\r\n\r\n const expandString = odataUrlPart.expandedODataUrlParts.length\r\n ? `$expand=${odataUrlPart.expandedODataUrlParts\r\n .map((currUrlPart) => {\r\n return this.generateODataUrlStringFragments(currUrlPart);\r\n })\r\n .join(',')}`\r\n : '';\r\n\r\n const countString = odataUrlPart.useCount ? '$count=true' : '';\r\n const topString = odataUrlPart.top !== null ? `$top=${odataUrlPart.top}` : '';\r\n\r\n const atRootLevel = odataUrlPart.propertyName === null;\r\n const concatenationCharacter = atRootLevel ? '&' : ';';\r\n\r\n // If we are at the root level, we concatenate things a little differently\r\n const stringsToCombine = [\r\n filtersString,\r\n selectorsString,\r\n expandString,\r\n countString,\r\n topString,\r\n ].filter((v) => v);\r\n if (stringsToCombine.length) {\r\n if (atRootLevel) {\r\n returnValue += stringsToCombine.join(concatenationCharacter);\r\n } else {\r\n returnValue += `(${stringsToCombine.join(concatenationCharacter)})`;\r\n }\r\n }\r\n\r\n return returnValue;\r\n }\r\n\r\n public static generateODataUrlString(query: ODataQuery): string {\r\n if (!query?.oDataClass) {\r\n throw new Error('Missing OData class.');\r\n }\r\n\r\n const oDataResourceName =\r\n ((new (query.oDataClass as Ctor)() as unknown) as IODataResource).oDataResourceName || '';\r\n\r\n if (!oDataResourceName) {\r\n throw new Error('Missing OData resource name.');\r\n }\r\n\r\n const oDataUrlParts = this.generateODataUrlPart(query);\r\n const oDataUrlString = this.generateODataUrlStringFragments(oDataUrlParts);\r\n\r\n let returnValue = `${oDataResourceName}`;\r\n\r\n if (oDataUrlString.length) {\r\n returnValue += `?${oDataUrlString}`;\r\n }\r\n\r\n return returnValue;\r\n }\r\n}\r\n\r\n// A builder class for OData queries\r\n\r\nexport class ODataQueryBuilder {\r\n private rootQuery!: ODataQuery;\r\n private currentQuery!: ODataQuery | ExpandedODataQuery;\r\n\r\n constructor(oDataClass: Ctor) {\r\n this.rootQuery = {\r\n oDataClass: oDataClass as Ctor,\r\n expandedQueries: [],\r\n filters: [],\r\n selectors: [],\r\n useCount: false,\r\n top: null,\r\n };\r\n\r\n this.currentQuery = this.rootQuery;\r\n }\r\n\r\n public getQueryObject(): ODataQuery {\r\n return this.rootQuery;\r\n }\r\n\r\n public filter(\r\n propertyName: keyof T,\r\n filterType: ODataQueryFilterTypes,\r\n filterValue: string | number | boolean | Date | ODataQueryFilter | null,\r\n ): ODataQueryBuilder {\r\n this.currentQuery.filters?.push({\r\n propertyName: propertyName as string,\r\n type: filterType,\r\n value: filterValue,\r\n });\r\n\r\n return this;\r\n }\r\n\r\n // NOTE: We provide the type parameter here when we are selecting something after an \"expand\" call and need to\r\n // explicitly specify the type that we want to select properties from.\r\n // Otherwise, the intellisense assumes the keys are for the main type T.\r\n public select(...propertyNames: (keyof T2)[]): ODataQueryBuilder {\r\n this.currentQuery.selectors?.push(...propertyNames.map((v) => v.toString()));\r\n return this;\r\n }\r\n\r\n // NOTE: This expands the query but the return type parameter remains pointed to the main type T\r\n public expand(propertyName: keyof T): ODataQueryBuilder {\r\n const existingQuery = this.rootQuery.expandedQueries?.find(\r\n (v) => v.propertyName === propertyName,\r\n );\r\n\r\n if (existingQuery) {\r\n this.currentQuery = existingQuery;\r\n } else {\r\n const newExpandedQuery: ExpandedODataQuery = {\r\n oDataClass: null,\r\n propertyName: propertyName as string,\r\n expandedQueries: [],\r\n filters: [],\r\n selectors: [],\r\n useCount: false,\r\n top: null,\r\n };\r\n\r\n this.rootQuery.expandedQueries?.push(newExpandedQuery);\r\n this.currentQuery = newExpandedQuery;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n // NOTE: This expands the query but the return type parameter remains pointed to the main type T\r\n public thenExpand(propertyName: keyof T2): ODataQueryBuilder {\r\n const existingQuery = this.currentQuery.expandedQueries?.find(\r\n (v) => v.propertyName === propertyName,\r\n );\r\n\r\n if (existingQuery) {\r\n this.currentQuery = existingQuery;\r\n } else {\r\n const newExpandedQuery: ExpandedODataQuery = {\r\n oDataClass: null,\r\n propertyName: propertyName as string,\r\n expandedQueries: [],\r\n filters: [],\r\n selectors: [],\r\n useCount: false,\r\n top: null,\r\n };\r\n\r\n this.currentQuery.expandedQueries?.push(newExpandedQuery);\r\n this.currentQuery = newExpandedQuery;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n public count(): ODataQueryBuilder {\r\n this.currentQuery.useCount = true;\r\n return this;\r\n }\r\n\r\n public top(topValue: number): ODataQueryBuilder {\r\n this.currentQuery.top = topValue;\r\n return this;\r\n }\r\n}\r\n","const UserRolesValues = {\r\n Contributor: 'Contributor',\r\n ProjectAdmin: 'ProjectAdmin',\r\n Admin: 'Admin',\r\n BidDaySupport: 'BidDaySupport',\r\n};\r\n\r\nconst UserRolesDisplayNames = {\r\n Contributor: 'Contributor',\r\n ProjectAdmin: 'Project Admin',\r\n Admin: 'Admin',\r\n BidDaySupport: 'Bid Day Support',\r\n};\r\n\r\nexport { UserRolesValues, UserRolesDisplayNames };\r\n","import { UserRolesValues } from '../../constants/users/user-roles';\r\n\r\nexport class UserInformation {\r\n public static from(json: unknown): UserInformation {\r\n return Object.assign(new UserInformation('', '', '', '', [], false), json);\r\n }\r\n\r\n id: string;\r\n email: string;\r\n name: string;\r\n location: string;\r\n roles: UserRole[];\r\n isLicensed: boolean;\r\n\r\n constructor(\r\n id: string,\r\n email: string,\r\n name: string,\r\n location: string,\r\n roles: UserRole[],\r\n licensed: boolean,\r\n ) {\r\n this.id = id;\r\n this.email = email;\r\n this.name = name;\r\n this.location = location;\r\n this.roles = roles;\r\n this.isLicensed = licensed;\r\n }\r\n\r\n public userIsAdmin(): boolean {\r\n return this.isUserAuthorized(UserRolesValues.Admin);\r\n }\r\n\r\n public userIsBidDaySupport(): boolean {\r\n return this.isUserAuthorized(UserRolesValues.BidDaySupport);\r\n }\r\n\r\n public userIsProjectAdmin(): boolean {\r\n return this.isUserAuthorized(UserRolesValues.ProjectAdmin);\r\n }\r\n\r\n public userIsContributor(): boolean {\r\n return this.isUserAuthorized(UserRolesValues.Contributor);\r\n }\r\n\r\n private isUserAuthorized(userRole: string): boolean {\r\n return this.roles.find((v) => v.id === userRole) !== undefined;\r\n }\r\n}\r\n","import { UserRolesDisplayNames, UserRolesValues } from './user-roles';\r\n\r\nconst UserRoles: { [index: string]: UserRole } = {\r\n Contributor: { id: UserRolesValues.Contributor, name: UserRolesDisplayNames.Contributor },\r\n ProjectAdmin: { id: UserRolesValues.ProjectAdmin, name: UserRolesDisplayNames.ProjectAdmin },\r\n Admin: { id: UserRolesValues.Admin, name: UserRolesDisplayNames.Admin },\r\n BidDaySupport: { id: UserRolesValues.BidDaySupport, name: UserRolesDisplayNames.BidDaySupport },\r\n Dev: { id: 'Dev', name: 'Dev' },\r\n};\r\n\r\nexport default UserRoles;\r\n","const getConfig = (key: string): string | undefined => {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const env = (window as any).ENV;\r\n const configVal = env && env[key];\r\n\r\n if (configVal) {\r\n return configVal;\r\n }\r\n\r\n return process.env[key];\r\n};\r\n\r\nexport { getConfig };\r\n","import axios, { AxiosInstance } from 'axios';\r\nimport axiosMiddleware from '../../extensions/axiosMiddleware';\r\nimport { getConfig } from '../../utils/config';\r\nimport { AuthenticationService } from '../authentication/authentication-service';\r\n\r\ninterface AuthHeaders {\r\n Authorization: string;\r\n AppAuth: string | null;\r\n}\r\n\r\nexport class CommandHttpService {\r\n private static commandApiUrl = getConfig('REACT_APP_COMMAND_API_URL') as string;\r\n private static commandApiScope = getConfig('REACT_APP_MSAL_COMMAND_API_SCOPE') as string;\r\n\r\n public static async getCommandHttpService(): Promise {\r\n const authHeaders = await CommandHttpService.getAuthHeaders();\r\n\r\n const service = axios.create({\r\n baseURL: this.commandApiUrl,\r\n headers: authHeaders,\r\n });\r\n\r\n // set up custom axios interceptors for dates, auth tokens, and to clean up request encoding\r\n axiosMiddleware.setMiddleware(service);\r\n\r\n return service;\r\n }\r\n\r\n public static getApiUrl(): string {\r\n return this.commandApiUrl;\r\n }\r\n\r\n public static async getAuthHeaders(): Promise {\r\n const accessToken = await AuthenticationService.getAccessToken(this.commandApiScope);\r\n if (!accessToken) {\r\n throw Error('Could not retrieve access token');\r\n }\r\n\r\n return {\r\n Authorization: `Bearer ${accessToken}`,\r\n AppAuth: AuthenticationService.getAuthToken(),\r\n };\r\n }\r\n}\r\n","import { CommandHttpService } from '../command/command-http-service';\n\n// returns an authorization token if login successful\nconst loginUser = async (targetClientOrgId: string | null): Promise => {\n const service = await CommandHttpService.getCommandHttpService();\n const response = await service.post(`/login${targetClientOrgId ? '/' + targetClientOrgId : ''}`);\n if (response.data) {\n return response.data;\n }\n return null;\n};\n\nconst getClientOrganizations = async (): Promise => {\n const service = await CommandHttpService.getCommandHttpService();\n const response = await service.get('/login/client-organizations');\n return response.data;\n};\n\nexport default {\n loginUser,\n getClientOrganizations,\n};\n","export class User implements IODataResource {\r\n public readonly oDataResourceName = 'User';\r\n\r\n public id!: string;\r\n public email!: string;\r\n public location!: string;\r\n public roles!: string[];\r\n public name!: string;\r\n}\r\n","import axios, { AxiosInstance } from 'axios';\nimport axiosMiddleware from '../../extensions/axiosMiddleware';\nimport { getConfig } from '../../utils/config';\nimport { AuthenticationService } from '../authentication/authentication-service';\n\nexport class QueryHttpService {\n private static queryApiUrl = getConfig('REACT_APP_QUERY_API_URL') as string;\n private static queryApiScope = getConfig('REACT_APP_MSAL_QUERY_API_SCOPE') as string;\n\n public static async getQueryService(): Promise {\n const accessToken = await AuthenticationService.getAccessToken(this.queryApiScope);\n if (!accessToken) {\n throw Error('Could not retrieve access token');\n }\n const service = axios.create({\n baseURL: this.queryApiUrl,\n headers: {\n Authorization: `Bearer ${accessToken}`,\n AppAuth: AuthenticationService.getAuthToken(),\n },\n });\n\n // set up custom axios interceptors for dates, auth tokens, and to clean up request encoding\n axiosMiddleware.setMiddleware(service);\n\n return service;\n }\n\n public static getApiUrl(): string {\n return this.queryApiUrl;\n }\n}\n","import { User as UserData } from '../../classes/odata/user';\r\nimport UserRoles from '../../constants/users';\r\nimport { CommandHttpService } from '../command/command-http-service';\r\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\r\nimport { ODataHttpService } from '../odata/odata-http-service';\r\nimport { QueryHttpService } from '../query/query-http-service';\r\n\r\nconst userFromData = (data: UserData): User => {\r\n return {\r\n isNew: false,\r\n id: data.id,\r\n email: data.email.toLowerCase(),\r\n location: data.location,\r\n roles: data.roles.map((role) => {\r\n return UserRoles[role];\r\n }),\r\n name: data.name,\r\n };\r\n};\r\n\r\n// Query Service API\r\n\r\nconst getAllUsers = async (): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(UserData).getQueryObject();\r\n const userData = await ODataHttpService.toArray(oDataQuery);\r\n const users = userData.map(userFromData);\r\n\r\n return users;\r\n};\r\n\r\nconst getUserById = async (id: string): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(UserData)\r\n .filter('id', 'equals', id)\r\n .getQueryObject();\r\n\r\n const result = await ODataHttpService.firstOrDefault(oDataQuery);\r\n if (!result) {\r\n return null;\r\n }\r\n return userFromData(result);\r\n};\r\n\r\nconst getUserByEmail = async (email: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(`/users/${email}`);\r\n\r\n if (response.data) {\r\n return userFromData(response.data);\r\n }\r\n return null;\r\n};\r\n\r\n// Command Service API\r\n\r\nconst addUser = async (user: User): Promise => {\r\n const dto: UserDTO = {\r\n email: user.email,\r\n location: user.location,\r\n roles: user.roles.map((r) => r.id),\r\n };\r\n\r\n const service = await CommandHttpService.getCommandHttpService();\r\n await service.post('/user', dto);\r\n return user;\r\n};\r\n\r\nconst deleteUser = async (user: User): Promise => {\r\n const service = await CommandHttpService.getCommandHttpService();\r\n await service.delete('/user', {\r\n params: { email: user.email },\r\n });\r\n};\r\n\r\nconst editUser = async (user: User): Promise => {\r\n const dto: UserDTO = {\r\n email: user.email,\r\n location: user.location,\r\n roles: user.roles.map((r) => r.id),\r\n };\r\n\r\n const service = await CommandHttpService.getCommandHttpService();\r\n await service.put('/user', dto);\r\n};\r\n\r\nconst getCurrentUser = async (): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(`/users/current-user`);\r\n const user = userFromData(response.data);\r\n return user;\r\n};\r\n\r\nexport default {\r\n addUser,\r\n deleteUser,\r\n editUser,\r\n getAllUsers,\r\n getUserById,\r\n getUserByEmail,\r\n getCurrentUser,\r\n};\r\n","import * as Msal from 'msal';\r\nimport { Configuration } from 'msal';\r\nimport { UserInformation } from '../../app/auth/user';\r\nimport UserRoles from '../../constants/users';\r\nimport { getConfig } from '../../utils/config';\r\nimport LoginApi from '../login/login-service';\r\nimport UserApi from '../users/user-service';\r\n\r\nconst { localStorage } = window;\r\nconst TARGET_CLIENT_ORG_ID = 'TargetClientOrgId';\r\n\r\nexport enum SSOPasswordResetStatus {\r\n None = 'none',\r\n Initiated = 'initiated',\r\n Completed = 'completed',\r\n}\r\n\r\nexport enum SSOErrorCode {\r\n OtherError = 1,\r\n LicensingAppSSOError = 2,\r\n}\r\n\r\nexport interface SSOError {\r\n message: string;\r\n code: SSOErrorCode;\r\n}\r\n\r\nexport class AuthenticationService {\r\n private static SSOError: 'SSOError';\r\n private static SSOPasswordResetStatus = 'ssoPasswordResetStatus';\r\n private static BidDayAuthToken = 'BidDayAuthToken';\r\n private static loginScopes = getConfig('REACT_APP_MSAL_LOGIN_SCOPES') as string;\r\n private static queryApiScope = getConfig('REACT_APP_MSAL_QUERY_API_SCOPE') as string;\r\n private static commandApiScope = getConfig('REACT_APP_MSAL_COMMAND_API_SCOPE') as string;\r\n private static clientId = getConfig('REACT_APP_MSAL_CLIENTID') as string;\r\n private static signInAuthority = getConfig('REACT_APP_MSAL_AUTHORITY_SIGNIN') as string;\r\n private static passwordResetAuthority = getConfig(\r\n 'REACT_APP_MSAL_AUTHORITY_PASSWORDRESET',\r\n ) as string;\r\n private static redirectUri = getConfig('REACT_APP_MSAL_REDIRECT_URL') as string;\r\n private static cacheLocation = 'localStorage' as 'localStorage' | 'sessionStorage' | undefined;\r\n\r\n private static msalObj: Msal.UserAgentApplication;\r\n\r\n private static requestObj = {\r\n scopes: (AuthenticationService.loginScopes ?? '')\r\n .split(' ')\r\n .concat(AuthenticationService.queryApiScope, AuthenticationService.commandApiScope),\r\n };\r\n\r\n private static msalConfig: Configuration = {\r\n auth: {\r\n clientId: AuthenticationService.clientId,\r\n validateAuthority: false,\r\n redirectUri: AuthenticationService.redirectUri,\r\n postLogoutRedirectUri: AuthenticationService.redirectUri,\r\n },\r\n cache: {\r\n cacheLocation: AuthenticationService.cacheLocation,\r\n storeAuthStateInCookie: true,\r\n },\r\n system: {\r\n loadFrameTimeout: 15000,\r\n },\r\n };\r\n\r\n public static currentUserInfo: UserInformation | null = null;\r\n\r\n public static userIsAuthenticated(): boolean {\r\n if (!AuthenticationService.msalObj) {\r\n return false;\r\n }\r\n if (AuthenticationService.msalObj.getAccount()) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n public static userIsLoggedIn(): boolean {\r\n if (AuthenticationService.getAuthToken() && AuthenticationService.currentUserInfo) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Calls the command service's login endpoint to set the AppAuthToken in local storage\r\n *\r\n * @param authErrorMessage - The message to display to the user on failed auth\r\n * @param loginErrorMessage - The message to display to the user on failed login\r\n * @returns True if the BidDaySupport client selector should be displayed, false otherwise\r\n */\r\n public static async login(authErrorMessage: string, loginErrorMessage: string): Promise {\r\n try {\r\n const targetClientOrgId = localStorage.getItem(TARGET_CLIENT_ORG_ID);\r\n const authToken = await LoginApi.loginUser(targetClientOrgId);\r\n const tokenParts = authToken?.split('.') ?? [];\r\n\r\n // NOTE: JWTs are made of 3 parts -- header, payload, and signature\r\n // We use the payload below to check if the user has the BidDaySupport role\r\n // so we verify the token is not malformed here\r\n if (authToken && tokenParts.length === 3) {\r\n localStorage.setItem(AuthenticationService.BidDayAuthToken, authToken);\r\n } else {\r\n throw new Error(authErrorMessage);\r\n }\r\n\r\n // Check token payload for BidDaySupport role\r\n // NOTE: If the user has only one role, tokenPayload.role will be a string instead of an array\r\n const tokenPayload = JSON.parse(atob(tokenParts[1]));\r\n const roles: string[] =\r\n typeof tokenPayload.role === 'string' ? [tokenPayload.role] : tokenPayload.role ?? [];\r\n const isBidDaySupport = roles.some((role) => role === UserRoles.BidDaySupport.id);\r\n\r\n // If the user has the BidDaySupport role and has not selected a client,\r\n // return true here so the caller knows to display the client selector\r\n if (isBidDaySupport && !targetClientOrgId) {\r\n return true;\r\n }\r\n\r\n // Get user info\r\n AuthenticationService.currentUserInfo = await AuthenticationService.loadUserInfo();\r\n if (!AuthenticationService.currentUserInfo) {\r\n throw new Error(loginErrorMessage);\r\n }\r\n AuthenticationService.currentUserInfo.isLicensed = true;\r\n\r\n // If we made it this far, either the user is not a BidDaySupport user\r\n // or they have a targetClientOrgId set. Return false here so the caller\r\n // knows they do not need to display the client selector\r\n return false;\r\n } catch (err) {\r\n const error = err as any; // eslint-disable-line @typescript-eslint/no-explicit-any\r\n if (\r\n error.isAxiosError &&\r\n error.response &&\r\n error.response.data &&\r\n error.response.data.status === 422 &&\r\n error.response.data.detail === 'Unable to obtain a license'\r\n ) {\r\n const account = AuthenticationService.msalObj.getAccount();\r\n this.setUnknownUserInfo(account);\r\n throw new Error('Unlicensed');\r\n }\r\n throw new Error(loginErrorMessage);\r\n }\r\n }\r\n\r\n private static async loadUserInfo(): Promise {\r\n const targetClientOrgId = localStorage.getItem(TARGET_CLIENT_ORG_ID);\r\n // We only want to allow this process to be skipped if we aren't dealing with a Bid Day Support user\r\n // The login flow for Bid Day Support requires login to be called twice, so we want the second login's permissions\r\n // to be able to be persisted in that case\r\n if (AuthenticationService.currentUserInfo && !targetClientOrgId) {\r\n return AuthenticationService.currentUserInfo;\r\n } else {\r\n const account = AuthenticationService.msalObj.getAccount();\r\n\r\n if (account) {\r\n try {\r\n const user = await UserApi.getCurrentUser();\r\n if (user) {\r\n AuthenticationService.currentUserInfo = UserInformation.from(user);\r\n AuthenticationService.currentUserInfo.name = account.name;\r\n return AuthenticationService.currentUserInfo;\r\n }\r\n } catch (error) {\r\n // TODO: log the issue with AppInsights\r\n }\r\n // The user has been authenticated, and their organization has a license\r\n // but there is no User record for them in the system.\r\n // Since we couldn't find a user record, populate info from authentication token.\r\n // They won't have any roles, but can have read-only access to anything that does not require a specific role to see\r\n this.setUnknownUserInfo(account);\r\n return AuthenticationService.currentUserInfo;\r\n }\r\n return null;\r\n }\r\n }\r\n\r\n public static init(genericErrorMessage: string): void {\r\n AuthenticationService.msalObj = new Msal.UserAgentApplication(AuthenticationService.msalConfig);\r\n AuthenticationService.setAuthRedirectCallBack(genericErrorMessage);\r\n }\r\n\r\n public static signIn(): void {\r\n // Clear out all of local storage, which will include MSAL specific things in addition to what this\r\n // app puts there (basic auth / user info).\r\n localStorage.clear();\r\n\r\n // Reset the password reset status local storage variable\r\n AuthenticationService.clearPasswordResetStatus();\r\n\r\n // Note: The loginRedirect() method uses the currently configured 'authority' property on the\r\n // msalObj to know whether to navigate to a sign-in or password reset b2c form\r\n AuthenticationService.msalObj.authority = AuthenticationService.signInAuthority;\r\n AuthenticationService.msalObj.loginRedirect(this.requestObj);\r\n }\r\n\r\n public static resetPassword(): void {\r\n // Note: The loginRedirect() method uses the currently configured 'authority' property on the\r\n // msalObj to know whether to navigate to a sign-in or password reset b2c form\r\n AuthenticationService.msalObj.authority = AuthenticationService.passwordResetAuthority;\r\n AuthenticationService.msalObj.loginRedirect(this.requestObj);\r\n }\r\n\r\n public static logout(): void {\r\n localStorage.clear();\r\n AuthenticationService.currentUserInfo = null;\r\n // Note: The msalObj.logout() method redirects to an SSO logout page so it can clear cookies for that domain, then redirects back to our app\r\n AuthenticationService.msalObj.authority = AuthenticationService.signInAuthority;\r\n AuthenticationService.msalObj.logout();\r\n }\r\n\r\n public static async getAccessToken(scope: string): Promise {\r\n try {\r\n AuthenticationService.msalObj.authority = AuthenticationService.signInAuthority;\r\n const response = await AuthenticationService.msalObj.acquireTokenSilent({ scopes: [scope] });\r\n return response.accessToken;\r\n } catch (err) {\r\n const error = err as any; // eslint-disable-line @typescript-eslint/no-explicit-any\r\n if (error.errorCode === 'interaction_required') {\r\n // user must log in again\r\n AuthenticationService.logout();\r\n } else {\r\n throw error;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n public static getAuthToken(): string | null {\r\n return localStorage.getItem(AuthenticationService.BidDayAuthToken);\r\n }\r\n\r\n public static urlContainsSSOHash(hash: string): boolean {\r\n return AuthenticationService.msalObj.urlContainsHash(hash);\r\n }\r\n\r\n public static getLastError(): SSOError | null {\r\n const e = localStorage.getItem(AuthenticationService.SSOError);\r\n if (e) {\r\n return JSON.parse(e) as SSOError;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n public static clearLastError(): void {\r\n localStorage.removeItem(AuthenticationService.SSOError);\r\n }\r\n\r\n public static getPasswordResetStatus(): SSOPasswordResetStatus {\r\n const status = localStorage.getItem(AuthenticationService.SSOPasswordResetStatus);\r\n if (status) {\r\n return (status as keyof typeof SSOPasswordResetStatus) as SSOPasswordResetStatus;\r\n } else {\r\n return SSOPasswordResetStatus.None;\r\n }\r\n }\r\n\r\n public static clearPasswordResetStatus(): void {\r\n localStorage.setItem(AuthenticationService.SSOPasswordResetStatus, SSOPasswordResetStatus.None);\r\n }\r\n\r\n private static setAuthRedirectCallBack(genericErrorMessage: string): void {\r\n AuthenticationService.msalObj.handleRedirectCallback(\r\n async (error: Msal.AuthError, response?: Msal.AuthResponse): Promise => {\r\n if (error) {\r\n // NOTE: There are 3 error codes that require user interaction so we want to redirect the user to\r\n // the SSO login page if this is the case.\r\n // https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-handling-exceptions?tabs=javascript\r\n if (\r\n ['consent_required', 'interaction_required', 'login_required'].includes(error.errorCode)\r\n ) {\r\n AuthenticationService.msalObj.loginRedirect(this.requestObj);\r\n return;\r\n }\r\n\r\n // If we have received an error code, we set necessary local storage\r\n error.message = error.message || '';\r\n if (error.message.indexOf('AADB2C90118') > -1) {\r\n // If we received the password reset error code, set a local storage variable\r\n localStorage.setItem(\r\n AuthenticationService.SSOPasswordResetStatus,\r\n SSOPasswordResetStatus.Initiated,\r\n );\r\n // then redirect to the password reset\r\n AuthenticationService.resetPassword();\r\n return;\r\n } else if (error.message.indexOf('AADB2C90091') > -1) {\r\n // Else if we received the password reset cancelled error code, reset status and return\r\n localStorage.setItem(\r\n AuthenticationService.SSOPasswordResetStatus,\r\n SSOPasswordResetStatus.None,\r\n );\r\n return;\r\n } else {\r\n // Else we set an SSOError based on the error code received\r\n this.setSSOErrors(error.message, genericErrorMessage);\r\n }\r\n } else {\r\n if (response) {\r\n // NOTE: The token claim below indicates that a password change has been completed.\r\n // If it exists, we create a localStorage variable for other code to use.\r\n if (\r\n response.idTokenClaims &&\r\n response.idTokenClaims.acr &&\r\n response.idTokenClaims.acr === 'b2c_1a_passwordreset'\r\n ) {\r\n localStorage.setItem(\r\n AuthenticationService.SSOPasswordResetStatus,\r\n SSOPasswordResetStatus.Completed,\r\n );\r\n // make sure we log out so user has to log in with new credentials\r\n AuthenticationService.msalObj.authority = AuthenticationService.signInAuthority;\r\n AuthenticationService.msalObj.logout();\r\n }\r\n }\r\n }\r\n },\r\n );\r\n }\r\n\r\n // If SSO errors come into our app, they come in as a URL hash.\r\n // This code will read the errors and then set a local storage variable.\r\n // The MSAL code will then run, strip the hash off the URL, and refresh the page.\r\n private static setSSOErrors(errorDescription: string, genericErrorMessage: string): void {\r\n let errorCode = SSOErrorCode.OtherError;\r\n\r\n // Certain error codes will need to be handled differently, so here we set an enum value based on the error received\r\n if (errorDescription.indexOf('AADB2C') > -1) {\r\n errorCode = SSOErrorCode.LicensingAppSSOError;\r\n }\r\n\r\n // A typical error message might look as follows so we want to clean it up to make the error message more user-friendly:\r\n // AADB2C: No matching ogranization for 'destiniestimatordev.onmicrosoft.com'\r\n // Correlation ID: be38782a-e576-437e-b449-190ec9756c5e\r\n // Timestamp: 2020-02-11 18:05:50Z\r\n errorDescription = errorDescription.replace(/(\\r\\n|\\r|\\n)/g, '').trim();\r\n errorDescription = errorDescription.replace(/^[\\w]+:/g, '').trim();\r\n errorDescription = errorDescription.replace(/Correlation ID.*$/gi, '').trim();\r\n\r\n // If the error message doesn't have a period at the end, add one\r\n if (!/\\.$/.test(errorDescription)) {\r\n errorDescription += '.';\r\n }\r\n\r\n const ssoError: SSOError = {\r\n message: errorDescription || genericErrorMessage,\r\n code: errorCode,\r\n };\r\n\r\n localStorage.setItem(AuthenticationService.SSOError, JSON.stringify(ssoError));\r\n }\r\n\r\n private static setUnknownUserInfo(account: Msal.Account): void {\r\n const userInfo: unknown = {\r\n id: '',\r\n email: account.idTokenClaims['email'],\r\n name: account.name,\r\n location: '',\r\n roles: [],\r\n isNew: false,\r\n isLicensed: false,\r\n };\r\n AuthenticationService.currentUserInfo = UserInformation.from(userInfo);\r\n }\r\n}\r\n","import { AxiosInstance } from 'axios';\nimport { AuthenticationService } from '../services/authentication/authentication-service';\n\nconst setMiddleware = (axiosToConfigure: AxiosInstance): void => {\n // default content type to JSON\n axiosToConfigure.defaults.headers['Content-Type'] = 'application/json';\n\n // replace '/' encoding (%2F) with %252F and '\\' encoding (%5C) with %255C as the former in both cases is prematurely\n // decoded on some web servers which breaks the ajax call.\n axiosToConfigure.interceptors.request.use((config) => {\n if (config.url) {\n config.url = config.url.replace(/%2F/gi, '%252F').replace(/%5C/gi, '%255C');\n }\n return config;\n });\n\n //Handle 401 responses\n axiosToConfigure.interceptors.response.use(\n async (response) => response,\n async (error) => {\n // NOTE: If there was an error and it wasn't from the server (ex. network issues), we want to explicitly\n // throw an exception, otherwise Axios will just return whatever we return from this callback function to\n // the calling code as a regular HTTP response.\n if (error && error.isAxiosError) {\n throw error;\n }\n\n if (error && error.response && error.response.status === 401) {\n AuthenticationService.logout();\n return error;\n }\n },\n );\n};\n\nexport default { setMiddleware };\n","import axios, { AxiosInstance } from 'axios';\r\nimport { plainToClass } from 'class-transformer';\r\nimport axiosMiddleware from '../../extensions/axiosMiddleware';\r\nimport { getConfig } from '../../utils/config';\r\nimport { AuthenticationService } from '../authentication/authentication-service';\r\nimport { BTODataService, ODataQuery } from './bt-odata-service';\r\n\r\nexport class ODataHttpService {\r\n private static oDataUrl = getConfig('REACT_APP_ODATA_URL') as string;\r\n private static queryApiScope = getConfig('REACT_APP_MSAL_QUERY_API_SCOPE') as string;\r\n\r\n private static async getODataHttpService(): Promise {\r\n const accessToken = await AuthenticationService.getAccessToken(ODataHttpService.queryApiScope);\r\n if (!accessToken) {\r\n throw Error('Could not retrieve access token');\r\n }\r\n\r\n const service = axios.create({\r\n baseURL: this.oDataUrl,\r\n headers: {\r\n Authorization: `Bearer ${accessToken}`,\r\n AppAuth: AuthenticationService.getAuthToken(),\r\n },\r\n });\r\n\r\n // set up custom axios interceptors for dates, auth tokens, and to clean up request encoding\r\n axiosMiddleware.setMiddleware(service);\r\n\r\n return service;\r\n }\r\n\r\n // NOTE: The type parameter for this method does NOT need to be an OData class, it can be whatever\r\n // we want the output to be cast as\r\n public static async firstOrDefault(queryObj: ODataQuery): Promise {\r\n return (await this.toArray(queryObj))[0] || null;\r\n }\r\n\r\n // NOTE: The type parameter for this method does NOT need to be an OData class, it can be whatever\r\n // we want the output to be cast as\r\n public static async toArray(queryObj: ODataQuery): Promise {\r\n const httpService = await ODataHttpService.getODataHttpService();\r\n const oDataUrlString = BTODataService.generateODataUrlString(queryObj);\r\n\r\n // NOTE: We do not do any real error handling in this code\r\n const response = await httpService.get(oDataUrlString);\r\n const responseValue: T[] = response?.data?.value;\r\n\r\n if (!responseValue || !responseValue.length) {\r\n return [];\r\n }\r\n\r\n return (responseValue.map((v) => plainToClass(queryObj.oDataClass!, v)) as unknown) as T[];\r\n }\r\n\r\n public static async fetch(query: string): Promise {\r\n const httpService = await ODataHttpService.getODataHttpService();\r\n\r\n // NOTE: We do not do any real error handling in this code\r\n const response = await httpService.get(query);\r\n const responseValue: T[] = response?.data?.value;\r\n\r\n if (!responseValue || !responseValue.length) {\r\n return [];\r\n }\r\n\r\n return responseValue as T[];\r\n }\r\n\r\n // Executes the provided odata query and returns the \"@odata.count\" property\r\n //\r\n // - NOTE: Count is not provided by default in odata, you should use ODataQueryBuilder.count() to include it\r\n // - NOTE: Since this ignores the \"value\" property in the odata response it is recommended to use ODataQueryBuilder.top(0) to reduce the response payload\r\n public static async getCount(queryObj: ODataQuery): Promise {\r\n const httpService = await ODataHttpService.getODataHttpService();\r\n const oDataUrlString = BTODataService.generateODataUrlString(queryObj);\r\n\r\n // NOTE: We do not do any real error handling in this code\r\n const response = await httpService.get(oDataUrlString);\r\n\r\n if (response.data['@odata.count'] === undefined) {\r\n throw new Error(\r\n 'Could not find the @odata.count property in the response body. This likely means the odata query did not set $count=true',\r\n );\r\n }\r\n\r\n const odataCount = response.data['@odata.count'] as number;\r\n return odataCount;\r\n }\r\n}\r\n","import { SystemValuesApi } from '..';\r\nimport { BidPackageDefinition as BidPackageDefinitionData } from '../../classes/odata/bid-package-definitions';\r\nimport SystemValues from '../../constants/system-values';\r\nimport { nameof } from '../../utils/nameof';\r\nimport { emptyUuid } from '../../utils/uuid';\r\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\r\nimport { ODataHttpService } from '../odata/odata-http-service';\r\n\r\n// Converts the odata for a bid package definition to the actual definition used by this web app\r\nconst bidPackageDefinitionFromData = (data: BidPackageDefinitionData): BidPackageDefinition => {\r\n return {\r\n id: data.id,\r\n code: data.code,\r\n description: data.description,\r\n tradeRequirementDefinitions: data.tradeRequirementDefinitions\r\n ? data.tradeRequirementDefinitions.map((t) => {\r\n return {\r\n id: t.id ?? emptyUuid,\r\n index: t.index ?? 0,\r\n description: t.description ?? '',\r\n requirementFulfillmentType: t.requirementFulfillmentType ?? 0,\r\n isNew: false,\r\n };\r\n })\r\n : [],\r\n lineItemDefinitions: data.lineItemDefinitions\r\n ? data.lineItemDefinitions.map(\r\n (l): BidPackageLineItemDefinition => {\r\n return {\r\n id: l.id,\r\n bidPackageDefinitionId: l.bidPackageDefinitionId,\r\n index: l.index,\r\n description: l.description,\r\n unitOfMeasure: l.unitOfMeasure,\r\n isNew: false,\r\n };\r\n },\r\n )\r\n : [],\r\n isNew: false,\r\n };\r\n};\r\n\r\n// Query Service API\r\nconst getAllBidPackageDefinitions = async (): Promise => {\r\n // lets get the code of the general conditions so we can filter it out\r\n const generalConditionsCode = await SystemValuesApi.getSystemValue(\r\n SystemValues.GENERAL_CONDITIONS_CODE,\r\n );\r\n\r\n // lets create the data query builder to search for bid packages.\r\n const dataQueryBuilder = new ODataQueryBuilder(\r\n BidPackageDefinitionData,\r\n );\r\n\r\n // did we get an actual value back for the general conditions code? if so, lets update the data query builder to filter out the general conditions package\r\n // its important that we add the filter before expanding the query to include the trade requirements\r\n if (generalConditionsCode) {\r\n dataQueryBuilder.filter(\r\n nameof('code'),\r\n 'not equals',\r\n generalConditionsCode,\r\n );\r\n }\r\n\r\n // the last thing we need to do is expand the query to include the trade requirements\r\n dataQueryBuilder.expand('tradeRequirementDefinitions');\r\n // now lets pull the data from the query service\r\n const oDataQuery = dataQueryBuilder.getQueryObject();\r\n\r\n const definitions = await ODataHttpService.toArray(oDataQuery);\r\n\r\n //TODO switch this method over to using the convert method above - MR\r\n return definitions.map((d) => {\r\n const definition: BidPackageDefinition = {\r\n ...d,\r\n isNew: false,\r\n tradeRequirementDefinitions: d.tradeRequirementDefinitions\r\n ? d.tradeRequirementDefinitions.map((t) => {\r\n return {\r\n ...t,\r\n isNew: false,\r\n };\r\n })\r\n : [],\r\n };\r\n return definition;\r\n });\r\n};\r\n\r\n// Gets the general condition bid package from the query api\r\nconst getGeneralConditionsDefinition = async (): Promise => {\r\n // lets get the code of the general conditions code so filter it out\r\n const generalConditionsCode = await SystemValuesApi.getSystemValue(\r\n SystemValues.GENERAL_CONDITIONS_CODE,\r\n );\r\n\r\n // did we get an actual value back? if we didnt, then we need to bounce out\r\n if (!generalConditionsCode) {\r\n return null;\r\n }\r\n\r\n const oDataQuery = new ODataQueryBuilder(BidPackageDefinitionData)\r\n // its important that we add the filter prior to expanding the query to include line item definitions\r\n .filter('code', 'equals', generalConditionsCode)\r\n .expand('lineItemDefinitions')\r\n .getQueryObject();\r\n\r\n const data = await ODataHttpService.firstOrDefault(oDataQuery);\r\n\r\n // were we able to get a general condition bid package?\r\n //lets massage the data a bit to return out the bid package definition from the odata version of the bid package definition\r\n return data ? bidPackageDefinitionFromData(data) : null;\r\n};\r\n\r\nexport default {\r\n getAllBidPackageDefinitions,\r\n getGeneralConditionsDefinition,\r\n};\r\n","export enum BidClassificationTypes {\r\n Unallocated = 0,\r\n SubBid = 1,\r\n Included = 2,\r\n MissingScope = 3,\r\n Risk = 4,\r\n OwnerAllow = 5,\r\n GeneralRequirement = 6,\r\n // NOTE: These are pseudo classification types\r\n Adjustment = 7,\r\n Totals = 8,\r\n}\r\n\r\nexport enum RequirementFulfillmentTypes {\r\n Quantitative = 0,\r\n Qualitative = 1,\r\n Freeform = 2,\r\n}\r\n","export enum BidderStatus {\r\n RequestCreated = 0,\r\n RequestSent = 1,\r\n QuoteReceived = 2,\r\n DeclinedToQuote = 3,\r\n QuoteIsLate = 4,\r\n}\r\n\r\nexport class Bidder implements IODataResource {\r\n public readonly oDataResourceName = 'Bidder';\r\n\r\n public bidPackageId: string | undefined;\r\n public companyName: string | undefined;\r\n public faxNumber: string | undefined;\r\n public fileUploadContainerId: string | undefined;\r\n public id: string | undefined;\r\n public notes: string | undefined;\r\n public notesId: string | undefined;\r\n public phoneNumber: string | undefined;\r\n public primaryContactEmail: string | undefined;\r\n public primaryContactName: string | undefined;\r\n public status: BidderStatus | undefined;\r\n public order: number | undefined;\r\n\r\n // NOTE: only needed for front-end\r\n public inEdit: boolean | undefined;\r\n public originalCompanyName: string | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n public hasExcludedStatus(): boolean {\r\n return (\r\n this.status === undefined ||\r\n this.status === BidderStatus.DeclinedToQuote ||\r\n this.status === BidderStatus.QuoteIsLate\r\n );\r\n }\r\n\r\n public isSecondBidder(): boolean {\r\n return this.order === 1 && !this.hasExcludedStatus();\r\n }\r\n}\r\n","import Big from 'big.js';\r\nimport { MutableRefObject } from 'react';\r\nimport * as Scroll from 'react-scroll';\r\nimport GeneralConstants from './../constants/general/index';\r\nimport { getConfig } from './config';\r\n\r\nconst scrollToRef = (ref: MutableRefObject): void => {\r\n const currentRef = ref.current as HTMLElement;\r\n if (!currentRef) {\r\n return;\r\n }\r\n\r\n // Subtract 75 to account for the navbar\r\n const newScrollPosition = currentRef.offsetTop - 75;\r\n Scroll.animateScroll.scrollTo(newScrollPosition, { duration: 750 });\r\n};\r\n\r\nconst convertBigToNumber = (\r\n numberToConvert: Big,\r\n decimalPlaces: number,\r\n enableRounding = true,\r\n): number => {\r\n return numberToConvert\r\n .round(\r\n decimalPlaces,\r\n enableRounding\r\n ? GeneralConstants.ROUNDING_MODE.ROUND_HALF_UP\r\n : GeneralConstants.ROUNDING_MODE.TRUNCATE,\r\n )\r\n .toNumber();\r\n};\r\n\r\n// Returns the currency value for the provided number at 2-decimal precision\r\nconst formatNumberAsCurrency = (number: number | Big): string => {\r\n return formatNumberAsCurrencyCustomPrecision(\r\n number,\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MINIMUM_FRACTION_DIGITS,\r\n true,\r\n );\r\n};\r\n\r\n// Returns the currency value for the provided number at 5-decimal precision\r\nconst formatNumberAsCurrencyFull = (number: number | Big): string => {\r\n return formatNumberAsCurrencyCustomPrecision(\r\n number,\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MAXIMUM_FRACTION_DIGITS,\r\n false,\r\n );\r\n};\r\n\r\nconst formatNumberAsCurrencyCustomPrecision = (\r\n number: number | Big,\r\n decimalPlaces: number,\r\n enableRounding: boolean,\r\n): string => {\r\n // TODO - the formatting of numbers can differ by language, so we will need to wire that up.\r\n // Currently, this code just handle the US currency format.\r\n\r\n // If we weren't passed a Big, create one\r\n if (!(number instanceof Big)) {\r\n number = new Big(number);\r\n }\r\n number = convertBigToNumber(number, decimalPlaces, enableRounding);\r\n\r\n // https://flaviocopes.com/how-to-format-number-as-currency-javascript/\r\n const formatter = new Intl.NumberFormat(undefined, {\r\n style: 'currency',\r\n currency: 'USD',\r\n minimumFractionDigits: decimalPlaces,\r\n maximumFractionDigits: decimalPlaces,\r\n });\r\n\r\n return formatter.format(number as number);\r\n};\r\n\r\nconst formatNumberAsPercentage = (\r\n number: number | Big,\r\n minimumFractionDigits = GeneralConstants.PERCENT_MINIMUM_FRACTION_DIGITS,\r\n maximumFractionDigits = GeneralConstants.PERCENT_MAXIMUM_FRACTION_DIGITS,\r\n): string => {\r\n if (number instanceof Big) {\r\n number = convertBigToNumber(number, maximumFractionDigits);\r\n }\r\n\r\n // https://flaviocopes.com/how-to-format-number-as-currency-javascript/\r\n const formatter = new Intl.NumberFormat(undefined, {\r\n style: 'percent',\r\n minimumFractionDigits: minimumFractionDigits,\r\n maximumFractionDigits: maximumFractionDigits,\r\n });\r\n\r\n return formatter.format(number as number);\r\n};\r\n\r\nconst formatNumberAsDecimal = (\r\n number: number | Big,\r\n minimumFractionDigits = GeneralConstants.PERCENT_MINIMUM_FRACTION_DIGITS,\r\n maximumFractionDigits = GeneralConstants.PERCENT_MAXIMUM_FRACTION_DIGITS,\r\n): string => {\r\n if (number instanceof Big) {\r\n number = convertBigToNumber(number, maximumFractionDigits);\r\n }\r\n\r\n // https://flaviocopes.com/how-to-format-number-as-currency-javascript/\r\n const formatter = new Intl.NumberFormat(undefined, {\r\n style: 'decimal',\r\n minimumFractionDigits: minimumFractionDigits,\r\n maximumFractionDigits: maximumFractionDigits,\r\n });\r\n\r\n return formatter.format(number as number);\r\n};\r\n\r\nconst normalizeNullOrUndefined = (value: null | undefined | T): null | T => {\r\n if (value === undefined) {\r\n return null;\r\n }\r\n\r\n return value;\r\n};\r\n\r\nconst getEnvironmentName = (): string => {\r\n const currEnvironment = (getConfig('REACT_APP_ENVIRONMENT') || '').toLowerCase();\r\n return currEnvironment;\r\n};\r\n\r\nconst isEnvironment = (environment: 'local' | 'dev' | 'qa' | 'uat' | 'prod'): boolean => {\r\n const currEnvironment = getEnvironmentName();\r\n\r\n // If we are looking for the \"local\" environment, we consider an empty environment variable or one\r\n // with a value of \"local\"\r\n if (environment === 'local') {\r\n return (currEnvironment || 'local') === 'local';\r\n }\r\n\r\n return environment === currEnvironment;\r\n};\r\n\r\n// Determines if the user is on a small screen device, not just a mobile device,\r\n// since that can include tablets, which this should work on\r\nconst isSmallScreenDevice = (): boolean => {\r\n // NOTE: 768px is what Bootstrap uses to define a \"medium\" size screen and up\r\n return !window.matchMedia('(min-width: 768px)').matches;\r\n};\r\n\r\nexport {\r\n convertBigToNumber,\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n formatNumberAsPercentage,\r\n formatNumberAsDecimal,\r\n getEnvironmentName,\r\n isEnvironment,\r\n isSmallScreenDevice,\r\n normalizeNullOrUndefined,\r\n scrollToRef,\r\n};\r\n","import Big from 'big.js';\r\n\r\nconst sumBigNumbers = (args: Big[]): Big => {\r\n return args.reduce((accumulator, currValue) => {\r\n return accumulator.add(currValue);\r\n }, new Big(0));\r\n};\r\n\r\nconst convertToPercentage = (num: number): number | null => {\r\n if (isNaN(num)) {\r\n return null;\r\n }\r\n\r\n // NOTE: We use Big.js for this math to avoid floating point weirdness (ie: 0.7 / 100 == 0.006999)\r\n return new Big(num).div(100).toNumber();\r\n};\r\n\r\nexport { sumBigNumbers, convertToPercentage };\r\n","import { normalizeNullOrUndefined } from './general';\r\n\r\nconst isEmptyOrWhitespace = (text: string | null | undefined): boolean => {\r\n return normalizeNullOrUndefined(text) === null || text?.trim().length === 0;\r\n};\r\n\r\nconst doesStringExistInOtherString = (\r\n stringToCheck: string | null | undefined,\r\n searchString: string | null | undefined,\r\n caseSensitive = false,\r\n): boolean => {\r\n stringToCheck = stringToCheck ?? '';\r\n searchString = searchString ?? '';\r\n\r\n if (caseSensitive) {\r\n return stringToCheck.includes(searchString);\r\n }\r\n\r\n return stringToCheck.toLowerCase().includes(searchString.toLowerCase());\r\n};\r\n\r\nconst areTrimmedStringsEqual = (\r\n original: string | null | undefined,\r\n compareTo: string | null | undefined,\r\n useLocale = false,\r\n): boolean => {\r\n const trimmedOriginal = (original || '').trim();\r\n const trimmedCompareTo = (compareTo || '').trim();\r\n\r\n // Perform an equality comparison here to see if the values are equal prior to calling toLowerCase()\r\n if (trimmedOriginal === trimmedCompareTo) {\r\n return true;\r\n }\r\n\r\n return useLocale\r\n ? trimmedOriginal.toLocaleLowerCase() === trimmedCompareTo.toLocaleLowerCase()\r\n : trimmedOriginal.toLowerCase() === trimmedCompareTo.toLowerCase();\r\n};\r\n\r\nconst getDuplicates = (values: string[]): string[] => {\r\n const valuesWithoutDuplicates = [...new Set(values)];\r\n let duplicates = [...values];\r\n\r\n valuesWithoutDuplicates.forEach((item) => {\r\n const i = duplicates.indexOf(item);\r\n duplicates = duplicates.slice(0, i).concat(duplicates.slice(i + 1, duplicates.length));\r\n });\r\n\r\n return duplicates;\r\n};\r\n\r\nconst getEmailWithoutDomain = (email: string): string => {\r\n return email.split('@')[0];\r\n};\r\n\r\n// https://stackoverflow.com/a/46181/3661319\r\nconst isValidEmail = (email: string): boolean => {\r\n const pattern = /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\r\n return pattern.test(email);\r\n};\r\n\r\n// Verifies there are 10-15 digits\r\nconst isValidPhoneNumber = (phoneNumber: string): boolean => {\r\n const matches = phoneNumber.match(/\\d/g);\r\n if (!matches) {\r\n return false;\r\n }\r\n return matches.length > 9 && matches.length < 16;\r\n};\r\n\r\n// Returns an array of sanitized cells\r\nconst getSanitizedExcelRows = (excelClipboardText: string): string[][] | null => {\r\n // NOTE: Even if the string didn't contain tab characters, we still want to process it as one cell of data\r\n const rows: string[][] = [];\r\n\r\n // NOTE: We do not want to trim the string here, as it can cause cells to be offset\r\n // in some instances where empty cells exist at the beginning or end of a row.\r\n excelClipboardText.split('\\n').forEach((row) => {\r\n const cells = row.split('\\t');\r\n\r\n // Remove invisible characters from cells\r\n for (let i = 0; i < cells.length; i++) {\r\n cells[i] = cells[i].trim().replace(/[^\\S ]+/g, '');\r\n }\r\n\r\n // If the cells array is just a collection of emptiness, destined to be alone forever, ignore it\r\n if (cells.every((v) => (v || '').trim().length === 0)) {\r\n return;\r\n }\r\n\r\n rows.push(cells);\r\n });\r\n\r\n return rows;\r\n};\r\n\r\nconst getFileExtension = (filename: string): string | null => {\r\n if (!filename.includes('.')) {\r\n return null;\r\n }\r\n\r\n return filename.split('.').pop() as string;\r\n};\r\n\r\nconst escapeStringForRegExp = (text: string): string => {\r\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // $& means the whole matched string\r\n};\r\n\r\nconst removeNonNumericCharsFromString = (inputString: string): string => {\r\n // Remove anything that isn't numeric, a period, or a negative sign (dollar signs, commas, etc.)\r\n return inputString.replace(/[^\\d.-]/g, '');\r\n};\r\n\r\nexport {\r\n areTrimmedStringsEqual,\r\n doesStringExistInOtherString,\r\n getDuplicates,\r\n getEmailWithoutDomain,\r\n isValidEmail,\r\n isValidPhoneNumber,\r\n getSanitizedExcelRows,\r\n getFileExtension,\r\n isEmptyOrWhitespace,\r\n escapeStringForRegExp,\r\n removeNonNumericCharsFromString,\r\n};\r\n","export class Adjustment implements IODataResource, IEditableEntity {\r\n public readonly oDataResourceName = 'Adjustment';\r\n\r\n public isDirty = false;\r\n\r\n public id: string | undefined;\r\n public bidPackageId: string | undefined;\r\n public alternateId: string | undefined;\r\n public bidderId: string | undefined;\r\n public value: number | null | undefined;\r\n public notes: string | undefined;\r\n public notesId: string | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n // Merge in an existing adjustment, only setting things that have a value and that value is different\r\n // than the object's current value\r\n public mergeExistingAdjustment(adjustmentToMerge: Adjustment): void {\r\n if (adjustmentToMerge.notesId && this.notesId !== adjustmentToMerge.notesId) {\r\n this.notesId = adjustmentToMerge.notesId;\r\n }\r\n if (adjustmentToMerge.notes !== undefined && this.notes !== adjustmentToMerge.notes) {\r\n this.notes = adjustmentToMerge.notes;\r\n }\r\n if (adjustmentToMerge.value !== undefined && this.value !== adjustmentToMerge.value) {\r\n this.value = adjustmentToMerge.value;\r\n }\r\n }\r\n}\r\n","export class BidPackageBidClassificationTotal implements IODataResource {\r\n public readonly oDataResourceName = 'BidPackageBidClassificationTotals';\r\n\r\n public id: string | undefined;\r\n public bidPackageId: string | undefined;\r\n public bidderId: string | undefined;\r\n public alternateId: string | undefined;\r\n public classification: number | undefined;\r\n public amount: number | undefined;\r\n}\r\n","export class BidPackageBidTotal implements IODataResource, IEditableEntity {\r\n public readonly oDataResourceName = 'BidPackageBidTotal';\r\n\r\n public isDirty = false;\r\n\r\n public bidPackageId!: string;\r\n public bidderId!: string;\r\n public alternateId: string | undefined;\r\n public bidsTotal!: number;\r\n public adjustmentAmount!: number;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n}\r\n","import { BidClassificationTypes } from '../../app/enums/bid-package-enums';\r\n\r\nexport class BidPackageLineItemBid implements IODataResource, IEditableEntity {\r\n public readonly oDataResourceName = 'BidPackageLineItemBid';\r\n\r\n public isDirty = false;\r\n\r\n public bidPackageLineItemId: string | undefined;\r\n public bidderId: string | undefined;\r\n public classification: number | undefined;\r\n public id: string | undefined;\r\n public price: number | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n public static isBidValid(price: number | undefined, classification: number | undefined): boolean {\r\n price = price ?? undefined;\r\n classification = classification ?? undefined;\r\n\r\n switch (classification) {\r\n case BidClassificationTypes.Included:\r\n return price === undefined;\r\n\r\n case BidClassificationTypes.MissingScope:\r\n return price === undefined || typeof price === 'number';\r\n\r\n default:\r\n return price !== undefined && classification !== undefined && typeof price === 'number';\r\n }\r\n }\r\n}\r\n","export class BidPackageLineItemMetadata implements IODataResource {\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n public readonly oDataResourceName = 'BidPackageLineItemMetaData';\r\n\r\n public id: string | undefined;\r\n public bidPackageLineItemId: string | undefined;\r\n public name: string | undefined;\r\n public value: string | undefined;\r\n}\r\n","export class BidPackageLineItemOrder implements IODataResource {\n public constructor(init?: Partial) {\n Object.assign(this, init);\n }\n\n public readonly oDataResourceName = 'BidPackageLineItemOrder';\n\n public bidPackageLineItemId: string | undefined;\n public bidPackageLineItemGroupOrderId: string | undefined;\n public order: number | undefined;\n}\n","import Big from 'big.js';\r\nimport { Type } from 'class-transformer';\r\nimport { BidPackageLineItemBid } from './bid-package-line-item-bid';\r\nimport { BidPackageLineItemMetadata } from './bid-package-line-item-metadata';\r\nimport { BidPackageLineItemOrder } from './bid-package-line-item-order';\r\n\r\nexport class BidPackageLineItem implements IODataResource {\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n public readonly oDataResourceName = 'BidPackageLineItem';\r\n\r\n public alternateId: string | undefined; // If the bid package line item happens to tie to an alternate, this will be populated\r\n public baseEstimate: number | undefined;\r\n public bidPackageId: string | undefined;\r\n public description: string | undefined;\r\n public id: string | undefined;\r\n public quantity: number | undefined;\r\n public quantityUnitOfMeasure: string | undefined;\r\n public unitPrice: number | undefined;\r\n\r\n @Type(() => BidPackageLineItemBid)\r\n public bids: BidPackageLineItemBid[] = [];\r\n\r\n @Type(() => BidPackageLineItemMetadata)\r\n public metadata: BidPackageLineItemMetadata[] = [];\r\n\r\n @Type(() => BidPackageLineItemOrder)\r\n public mappedOrder: BidPackageLineItemOrder | undefined;\r\n\r\n // A method to calculate the current base estimate amount\r\n public static getBaseEstimate = (\r\n quantity: number | undefined,\r\n unitPrice: number | undefined,\r\n ): Big => {\r\n return new Big(quantity || 0).times(unitPrice || 0);\r\n };\r\n\r\n public getBaseEstimate(): Big {\r\n return BidPackageLineItem.getBaseEstimate(this.quantity, this.unitPrice);\r\n }\r\n\r\n public setMetadata(metadata: BidPackageLineItemMetadata): void {\r\n const copy = [...this.metadata];\r\n\r\n const index = this.metadata.findIndex((v) => v.name === metadata.name);\r\n if (index > -1) {\r\n copy[index].value = metadata.value;\r\n } else {\r\n copy.push(metadata);\r\n }\r\n\r\n this.metadata = copy;\r\n }\r\n\r\n public removeMetadata(id: string): void {\r\n const copy = [...this.metadata];\r\n const index = this.metadata.findIndex((v) => v.id === id);\r\n if (index > -1) {\r\n copy.splice(index, 1);\r\n }\r\n this.metadata = copy;\r\n }\r\n}\r\n","export class BidPackageLineItemRollupBid implements IODataResource, IEditableEntity {\r\n public readonly oDataResourceName = 'BidPackageLineItemRollupBid';\r\n\r\n public isDirty = false;\r\n\r\n public id: string | undefined;\r\n public bidPackageId: string | undefined;\r\n public bidderId: string | undefined;\r\n public alternateId: string | undefined;\r\n public metadataValue1: string | undefined;\r\n public metadataValue2: string | undefined;\r\n public bidValue: number | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n}\r\n","export class BidPackageLineItemsTotal implements IODataResource {\r\n public readonly oDataResourceName = 'BidPackageLineItemsTotal';\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n public bidPackageId: string | undefined;\r\n public alternateId: string | undefined;\r\n public total: number | undefined;\r\n}\r\n","export class BidPackageLineItemGroupOrder implements IODataResource {\n public constructor(init?: Partial) {\n Object.assign(this, init);\n }\n\n public readonly oDataResourceName: string = 'BidPackageLineItemGroupOrder';\n\n public bidPackageId: string | undefined;\n public classificationLevel1: string | undefined;\n public classificationLevel2: string | undefined;\n public order: number | undefined;\n public alternateId: string | undefined;\n\n public get groupingKey1(): string | undefined {\n return this.classificationLevel1;\n }\n\n public get groupingKey2(): string | undefined {\n return this.classificationLevel2;\n }\n}\n","import { BidClassificationTypes } from '../../app/enums/bid-package-enums';\r\n\r\nexport class BidPackageRequirementFulfillment implements IODataResource, IEditableEntity {\r\n public readonly oDataResourceName = 'BidPackageRequirementFulfillment';\r\n\r\n public isDirty = false;\r\n\r\n public bidPackageRequirementId: string | undefined;\r\n public id: string | undefined;\r\n public bidderId: string | undefined;\r\n public price: number | undefined;\r\n public classification: number | undefined;\r\n public value: string | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n public static isBidValid(price: number | undefined, classification: number | undefined): boolean {\r\n price = price ?? undefined;\r\n classification = classification ?? undefined;\r\n\r\n switch (classification) {\r\n case BidClassificationTypes.Included:\r\n if (price === undefined) {\r\n return true;\r\n }\r\n break;\r\n\r\n case BidClassificationTypes.MissingScope:\r\n return price === undefined || typeof price === 'number';\r\n\r\n // NOTE: We require a price for all classifications that aren't \"Included or MissingScope\"\r\n default:\r\n return classification !== undefined && price !== undefined && typeof price === 'number';\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n","import { Type } from 'class-transformer';\r\nimport { BidPackageRequirementFulfillment } from './bid-package-requirement-fulfillment';\r\n\r\n// NOTE: This class is intentionally not exposed directly via OData but\r\n// is able to be pulled back as an OData related entity\r\nexport class BidPackageRequirement implements IODataResource {\r\n public readonly oDataResourceName = 'BidPackageRequirement';\r\n\r\n public id: string | undefined;\r\n public bidPackageId: string | undefined;\r\n public requirementType: string | undefined;\r\n public description: string | undefined;\r\n public order: number | undefined;\r\n public requirementFulfillmentType: number | undefined;\r\n\r\n @Type(() => BidPackageRequirementFulfillment)\r\n public requirementFulfillments: BidPackageRequirementFulfillment[] = [];\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n}\r\n","export enum FeeTypes {\r\n Bid = 0, // Percentage of bid cost\r\n Total = 1, // Percentage of total cost\r\n Percent = 2, // Percentage of a user defined fee\r\n Subtotal = 3, // A subtotal\r\n LumpSum = 4, // A lumpsum\r\n}\r\n","import { Big } from 'big.js';\r\nimport { Type } from 'class-transformer';\r\nimport { clone, cloneDeep, orderBy, sortBy } from 'lodash';\r\nimport { BidClassificationTypes } from '../../app/enums/bid-package-enums';\r\nimport { normalizeNullOrUndefined } from '../../utils/general';\r\nimport { sumBigNumbers } from '../../utils/math';\r\nimport { areTrimmedStringsEqual } from '../../utils/strings';\r\nimport { Adjustment } from './adjustment';\r\nimport { Alternate } from './alternate';\r\nimport { BidPackageBidClassificationTotal } from './bid-package-bid-classification-total';\r\nimport { BidPackageBidTotal } from './bid-package-bid-total';\r\nimport { BidPackageContingencyAmount } from './bid-package-contingency-amount';\r\nimport { BidPackageLineItem } from './bid-package-line-item';\r\nimport { BidPackageLineItemBid } from './bid-package-line-item-bid';\r\nimport { BidPackageLineItemRollupBid } from './bid-package-line-item-rollup-bid';\r\nimport { BidPackageLineItemsTotal } from './bid-package-line-items-total';\r\nimport { BidPackageLineItemGroupOrder } from './bid-package-line-item-group-order';\r\nimport { BidPackageRequirement } from './bid-package-requirement';\r\nimport { BidPackageRequirementFulfillment } from './bid-package-requirement-fulfillment';\r\nimport { Bidder } from './bidder';\r\nimport { Project } from './project';\r\n\r\nexport class BidPackage implements IODataResource {\r\n @Type(() => Bidder)\r\n public readonly oDataResourceName = 'BidPackage';\r\n\r\n public assignedToUser: User | undefined;\r\n public assignedToUserId: string | undefined;\r\n public code!: string;\r\n public contingencyAmount: BidPackageContingencyAmount | undefined;\r\n public contingencyPercentage: number | undefined;\r\n public description: string | undefined;\r\n public id!: string;\r\n public isGeneralCondition: boolean | undefined;\r\n public lockedByUserEmail: string | null | undefined;\r\n public notes: string | undefined;\r\n public notesId: string | undefined;\r\n public project!: Project | undefined;\r\n public projectId!: string;\r\n public selectedBidder: Bidder | undefined;\r\n public selectedBidderId: string | undefined;\r\n public status: number | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n // NOTE: These navigation properties cannot be marked as nullable or undefined\r\n // or TS will complain when we try to expand OData properties\r\n @Type(() => BidPackageRequirement)\r\n public requirements: BidPackageRequirement[] = [];\r\n\r\n @Type(() => Bidder)\r\n public bidders: Bidder[] = [];\r\n\r\n @Type(() => BidPackageLineItem)\r\n public lineItems: BidPackageLineItem[] = [];\r\n\r\n @Type(() => BidPackageLineItemGroupOrder)\r\n public lineItemGroupOrders: BidPackageLineItemGroupOrder[] = [];\r\n\r\n @Type(() => BidPackageLineItemRollupBid)\r\n public lineItemRollupBids: BidPackageLineItemRollupBid[] = [];\r\n\r\n @Type(() => Adjustment)\r\n public adjustments: Adjustment[] = [];\r\n\r\n @Type(() => BidPackageBidClassificationTotal)\r\n public bidClassificationTotals: BidPackageBidClassificationTotal[] = [];\r\n\r\n @Type(() => BidPackageBidTotal)\r\n public bidTotals: BidPackageBidTotal[] = [];\r\n\r\n @Type(() => BidPackageLineItemsTotal)\r\n public lineItemsTotals: BidPackageLineItemsTotal[] = [];\r\n\r\n // Non-OData functionality\r\n public static getGeneralRequirements(\r\n requirements: BidPackageRequirement[],\r\n ): BidPackageRequirement[] {\r\n return sortBy(\r\n requirements.filter((v) => v.requirementType === 'General'),\r\n (v) => v.order,\r\n );\r\n }\r\n\r\n public static getTradeRequirements(\r\n requirements: BidPackageRequirement[],\r\n ): BidPackageRequirement[] {\r\n return sortBy(\r\n requirements.filter((v) => v.requirementType === 'Trade'),\r\n (v) => v.order,\r\n );\r\n }\r\n\r\n public getBaseEstimateAmount(alternateId: string | null): BidPackageLineItemsTotal | null {\r\n return (\r\n this.lineItemsTotals.find(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId),\r\n ) || null\r\n );\r\n }\r\n\r\n public getCurrentBidAmount(): Big {\r\n if (!this.selectedBidderId) {\r\n return Big(0);\r\n }\r\n\r\n const bidAmountInfo = this.getBaseBidAmountInfoForBidder(this.selectedBidderId, null);\r\n\r\n return bidAmountInfo.total;\r\n }\r\n\r\n // The base bid amount is the total of line item bids (no alternates),\r\n // bids on general / trade requirements, and the adjustment value.\r\n // We have bid totals calculated for this purpose, with the adjustment value explicitly broken out into its own field.\r\n public getBaseBidAmountInfoForBidder(\r\n bidderId: string | null,\r\n alternateId: string | null,\r\n ): {\r\n total: Big;\r\n adjustmentAmount: Big;\r\n } {\r\n const bidTotalForBidder = this.bidTotals.find(\r\n (v) =>\r\n normalizeNullOrUndefined(v.bidderId) ===\r\n normalizeNullOrUndefined(bidderId) &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId),\r\n );\r\n\r\n const total = new Big(bidTotalForBidder?.bidsTotal || 0).add(\r\n bidTotalForBidder?.adjustmentAmount || 0,\r\n );\r\n\r\n return {\r\n total: total,\r\n adjustmentAmount: new Big(bidTotalForBidder?.adjustmentAmount || 0),\r\n };\r\n }\r\n\r\n public getBidTotalForClassification(\r\n bidderId: string,\r\n classification: BidClassificationTypes,\r\n ): Big {\r\n // NOTE: These classification bid totals are broken down by an optional requirement type, but we don't care about\r\n // that breakdown here.\r\n // We do not include alternate classification totals.\r\n const classificationTotals = this.bidClassificationTotals.filter(\r\n (v) => v.bidderId === bidderId && !v.alternateId && v.classification === classification,\r\n );\r\n\r\n return classificationTotals.length\r\n ? sumBigNumbers(classificationTotals.map((v) => new Big(v.amount || 0)))\r\n : new Big(0);\r\n }\r\n\r\n public doUnleveledBidsExistForBidder(bidderId: string): boolean {\r\n // A bid is unleveled when there is no price and no classification (or the classification is the default).\r\n // NOTE: This includes all line items, including alternate line items.\r\n return this.lineItems.some(\r\n (v) =>\r\n !v.bids.some(\r\n (m) =>\r\n m.bidderId === bidderId &&\r\n !(\r\n normalizeNullOrUndefined(m.price) === null &&\r\n (m.classification === BidClassificationTypes.Unallocated ||\r\n normalizeNullOrUndefined(m.classification) === null)\r\n ),\r\n ),\r\n );\r\n }\r\n\r\n // #region Real-Time Calculation Methods\r\n\r\n public calculateLineItemBidValue(lineItem: BidPackageLineItem, bidderId: string): Big {\r\n const matchingBid = lineItem.bids.find((v) => v.bidderId === bidderId);\r\n if (matchingBid) {\r\n let calculatedBidPrice = new Big(0);\r\n\r\n switch (matchingBid.classification) {\r\n case BidClassificationTypes.MissingScope:\r\n // If the missing scope bid has a value, use it, otherwise calculate the value based on other bids\r\n if (matchingBid && normalizeNullOrUndefined(matchingBid.price) !== null) {\r\n calculatedBidPrice = new Big(matchingBid.price || 0);\r\n } else {\r\n const otherBids = sortBy(\r\n lineItem.bids.filter(\r\n (v) =>\r\n v.bidderId !== bidderId &&\r\n // NOTE: We don't have a value for included bids, so we want to exclude them from this logic, in case\r\n // there is a temporary value on a bid (as we change the classification from something else to \"Included\")\r\n // Additionally, we also want to exclude bids flagged as missing scope or risk.\r\n ![\r\n BidClassificationTypes.Included,\r\n BidClassificationTypes.MissingScope,\r\n BidClassificationTypes.Risk,\r\n ].includes(v.classification!) &&\r\n (v.price ?? 0) !== 0, // 0 bids should be ignored as these are considered default values and not eligible as placeholders\r\n ),\r\n (v) => v.price,\r\n );\r\n calculatedBidPrice = new Big(otherBids[0]?.price || lineItem.getBaseEstimate());\r\n }\r\n break;\r\n\r\n default:\r\n calculatedBidPrice = new Big(matchingBid?.price || 0);\r\n break;\r\n }\r\n\r\n return calculatedBidPrice;\r\n }\r\n\r\n return new Big(0);\r\n }\r\n\r\n public static calculateRequirementFulfillmentBidValue(\r\n requirement: BidPackageRequirement,\r\n bidderId: string,\r\n ): Big {\r\n const matchingBid = requirement.requirementFulfillments.find((v) => v.bidderId === bidderId);\r\n if (matchingBid) {\r\n let calculatedBidPrice = new Big(0);\r\n\r\n switch (matchingBid.classification) {\r\n case BidClassificationTypes.MissingScope:\r\n // If the missing scope bid has a value, use it, otherwise calculate the value based on other bids\r\n if (matchingBid && normalizeNullOrUndefined(matchingBid.price) !== null) {\r\n calculatedBidPrice = new Big(matchingBid.price || 0);\r\n } else {\r\n const otherBids = sortBy(\r\n requirement.requirementFulfillments.filter(\r\n (v) =>\r\n v.bidderId !== bidderId &&\r\n // NOTE: We don't have a value for included bids, so we want to exclude them from this logic, in case\r\n // there is a temporary value on a bid (as we change the classification from something else to \"Included\")\r\n // Additionally, we also want to exclude bids flagged as missing scope or risk.\r\n ![\r\n BidClassificationTypes.Included,\r\n BidClassificationTypes.MissingScope,\r\n BidClassificationTypes.Risk,\r\n ].includes(v.classification!) &&\r\n (v.price ?? 0) !== 0, // 0 bids should be ignored as these are considered default values and not eligible as placeholders\r\n ),\r\n (v) => v.price,\r\n );\r\n calculatedBidPrice = new Big(otherBids[0]?.price || 0);\r\n }\r\n break;\r\n\r\n default:\r\n calculatedBidPrice = new Big(matchingBid?.price || 0);\r\n break;\r\n }\r\n\r\n return calculatedBidPrice;\r\n }\r\n\r\n return new Big(0);\r\n }\r\n\r\n public calculateBidTotal(alternates: Alternate[]): Big {\r\n // Formula: Base bid amount + enabled alternate bid amounts + contingency amount\r\n const enabledAlternateIds: string[] = alternates.filter((v) => v.enabled).map((v) => v.id!);\r\n\r\n let baseBidAmount!: Big;\r\n let alternateBidsAmount!: Big;\r\n\r\n // For general condition bid packages, we don't have bidders so we want to use line item totals\r\n if (this.isGeneralCondition) {\r\n alternateBidsAmount = new Big(\r\n this.lineItemsTotals.find((v) => normalizeNullOrUndefined(v.alternateId) === null)\r\n ?.total ?? 0,\r\n );\r\n\r\n baseBidAmount = sumBigNumbers(\r\n enabledAlternateIds.map(\r\n (currAlternateId) =>\r\n new Big(\r\n this.lineItemsTotals.find(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(currAlternateId),\r\n )?.total ?? 0,\r\n ),\r\n ),\r\n );\r\n } else {\r\n alternateBidsAmount = this.selectedBidderId\r\n ? sumBigNumbers(\r\n enabledAlternateIds.map(\r\n (currAlternateId) =>\r\n this.getBaseBidAmountInfoForBidder(this.selectedBidderId!, currAlternateId)\r\n ?.total || new Big(0),\r\n ),\r\n )\r\n : new Big(0);\r\n\r\n baseBidAmount = this.selectedBidderId\r\n ? this.getBaseBidAmountInfoForBidder(this.selectedBidderId, null)?.total || new Big(0)\r\n : new Big(0);\r\n }\r\n\r\n const returnValue = baseBidAmount\r\n .add(alternateBidsAmount)\r\n .add(this.contingencyAmount?.contingencyAmount ?? 0);\r\n\r\n return returnValue;\r\n }\r\n\r\n // Utility functions that don't reference this object's values.\r\n public calculateVariancePercentage(amount1: Big, amount2: Big): Big {\r\n // Formula: (amount1 / amount2) - 1\r\n\r\n if (amount2.eq(0)) {\r\n return new Big(0);\r\n }\r\n\r\n // NOTE: We multiple by 100 to get the value as a percentage\r\n const returnValue = amount1.div(amount2).sub(1).mul(100);\r\n return returnValue;\r\n }\r\n\r\n public calculateVariance(amount1: Big, amount2: Big): Big {\r\n // Formula: amount1 - amount2\r\n const returnValue = amount1.sub(amount2);\r\n return returnValue;\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Line Item Bid Methods\r\n\r\n public getLineItemBid(lineItemId: string, bidderId: string): BidPackageLineItemBid | null {\r\n return (\r\n this.lineItems.find((v) => v.id === lineItemId)?.bids?.find((v) => v.bidderId === bidderId) ||\r\n null\r\n );\r\n }\r\n\r\n // Adds or updates a line item bid.\r\n // NOTE: The \"lineItemId\" parameter is required because it might not be present on the line item bid object.\r\n public setLineItemBid(\r\n lineItemId: string,\r\n newLineItemBid: BidPackageLineItemBid,\r\n doNotSetLineItemBidIfDirty = false,\r\n ): void {\r\n const lineItemToUpdateIndex = this.lineItems.findIndex((v) => v.id === lineItemId);\r\n\r\n if (lineItemToUpdateIndex > -1) {\r\n const lineItemToUpdate = cloneDeep(this.lineItems[lineItemToUpdateIndex]);\r\n\r\n const lineItemBidToAddOrUpdate = clone(newLineItemBid);\r\n\r\n const indexOfLineItemBidToUpdate = lineItemToUpdate.bids.findIndex(\r\n (v) => v.bidderId === newLineItemBid.bidderId,\r\n );\r\n\r\n if (indexOfLineItemBidToUpdate > -1) {\r\n // If the item we are about to update has unsaved changes for the current user, do not update it\r\n if (\r\n doNotSetLineItemBidIfDirty &&\r\n lineItemToUpdate.bids[indexOfLineItemBidToUpdate].isDirty\r\n ) {\r\n return;\r\n }\r\n\r\n const lineItemBidsCopy = [...lineItemToUpdate.bids];\r\n lineItemBidsCopy[indexOfLineItemBidToUpdate] = lineItemBidToAddOrUpdate;\r\n lineItemToUpdate.bids = lineItemBidsCopy;\r\n } else {\r\n lineItemToUpdate.bids = [...lineItemToUpdate.bids, lineItemBidToAddOrUpdate];\r\n }\r\n\r\n const lineItemsCopy = [...this.lineItems];\r\n lineItemsCopy[lineItemToUpdateIndex] = lineItemToUpdate;\r\n this.lineItems = lineItemsCopy;\r\n }\r\n }\r\n\r\n public deleteLineItemBid(\r\n lineItemId: string,\r\n bidderId: string,\r\n doNotSetLineItemBidIfDirty = false,\r\n ): void {\r\n const lineItemToUpdateIndex = this.lineItems.findIndex((v) => v.id === lineItemId);\r\n\r\n if (lineItemToUpdateIndex > -1) {\r\n const copy = clone(this.lineItems[lineItemToUpdateIndex]);\r\n\r\n const indexOfLineItemBidToDelete = copy.bids.findIndex((v) => v.bidderId === bidderId);\r\n\r\n if (indexOfLineItemBidToDelete > -1) {\r\n // If the item we are about to delete has unsaved changes for the current user, do not delete it\r\n if (doNotSetLineItemBidIfDirty && copy.bids[indexOfLineItemBidToDelete].isDirty) {\r\n return;\r\n }\r\n\r\n const lineItemBidsCopy = [...copy.bids];\r\n lineItemBidsCopy.splice(indexOfLineItemBidToDelete, 1);\r\n copy.bids = lineItemBidsCopy;\r\n\r\n const lineItemsCopy = [...this.lineItems];\r\n lineItemsCopy[lineItemToUpdateIndex] = copy;\r\n this.lineItems = lineItemsCopy;\r\n }\r\n }\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Line Item Rollup Bids Methods\r\n\r\n public static getLineItemRollupBids(\r\n allRollupBids: BidPackageLineItemRollupBid[],\r\n alternateId: string | null,\r\n ): BidPackageLineItemRollupBid[] {\r\n return allRollupBids.filter(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId),\r\n );\r\n }\r\n\r\n public getLineItemRollupBid(\r\n alternateId: string | null,\r\n bidderId: string,\r\n metadataValue1: string | null,\r\n metadataValue2: string | null,\r\n ): BidPackageLineItemRollupBid | null {\r\n return (\r\n this.lineItemRollupBids.find((v) => {\r\n return (\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId) &&\r\n v.bidderId === bidderId &&\r\n areTrimmedStringsEqual(v.metadataValue1 || null, metadataValue1) &&\r\n areTrimmedStringsEqual(v.metadataValue2 || null, metadataValue2)\r\n );\r\n }) || null\r\n );\r\n }\r\n\r\n public setLineItemRollupBid(\r\n newLineItemRollupBid: BidPackageLineItemRollupBid,\r\n doNotSetLineItemBidIfDirty = false,\r\n ): void {\r\n const indexOfBidToUpdate = this.lineItemRollupBids.findIndex(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(newLineItemRollupBid.alternateId) &&\r\n v.bidderId === newLineItemRollupBid.bidderId &&\r\n areTrimmedStringsEqual(\r\n v.metadataValue1 || null,\r\n newLineItemRollupBid.metadataValue1 || null,\r\n ) &&\r\n areTrimmedStringsEqual(\r\n v.metadataValue2 || null,\r\n newLineItemRollupBid.metadataValue2 || null,\r\n ),\r\n );\r\n\r\n const lineItemRollupBidToAddOrUpdate = clone(newLineItemRollupBid);\r\n\r\n if (indexOfBidToUpdate > -1) {\r\n // If the item we are about to update has unsaved changes for the current user, do not update it\r\n if (doNotSetLineItemBidIfDirty && this.lineItemRollupBids[indexOfBidToUpdate].isDirty) {\r\n return;\r\n }\r\n\r\n const lineItemRollupBidsCopy = [...this.lineItemRollupBids];\r\n lineItemRollupBidsCopy[indexOfBidToUpdate] = lineItemRollupBidToAddOrUpdate;\r\n this.lineItemRollupBids = lineItemRollupBidsCopy;\r\n } else {\r\n this.lineItemRollupBids = [...this.lineItemRollupBids, lineItemRollupBidToAddOrUpdate];\r\n }\r\n }\r\n\r\n public deleteLineItemRollupBid(\r\n alternateId: string | null,\r\n bidderId: string,\r\n metadataValue1: string | null,\r\n metadataValue2: string | null,\r\n doNotSetLineItemBidIfDirty = false,\r\n ): void {\r\n const indexOfBidToDelete = this.lineItemRollupBids.findIndex(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId) &&\r\n v.bidderId === bidderId &&\r\n areTrimmedStringsEqual(v.metadataValue1 || null, metadataValue1) &&\r\n areTrimmedStringsEqual(v.metadataValue2 || null, metadataValue2),\r\n );\r\n\r\n if (indexOfBidToDelete > -1) {\r\n // If the item we are about to update has unsaved changes for the current user, do not update it\r\n if (doNotSetLineItemBidIfDirty && this.lineItemRollupBids[indexOfBidToDelete].isDirty) {\r\n return;\r\n }\r\n\r\n const rollupBidsCopy = [...this.lineItemRollupBids];\r\n rollupBidsCopy.splice(indexOfBidToDelete, 1);\r\n this.lineItemRollupBids = rollupBidsCopy;\r\n }\r\n }\r\n\r\n //#endregion\r\n\r\n // #region Adjustment Methods\r\n\r\n public getAdjustment(alternateId: string | null, bidderId: string): Adjustment | null {\r\n return (\r\n this.adjustments.find(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId) && v.bidderId === bidderId,\r\n ) || null\r\n );\r\n }\r\n\r\n public setAdjustment(\r\n newAdjustment: Adjustment,\r\n mergeNewAdjustment: boolean,\r\n doNotSetLineItemBidIfDirty = false,\r\n ): void {\r\n const matchingAdjustmentIndex = this.adjustments.findIndex(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(newAdjustment.alternateId) &&\r\n v.bidderId === newAdjustment.bidderId,\r\n );\r\n\r\n if (matchingAdjustmentIndex > -1) {\r\n // If the item we are about to update has unsaved changes for the current user, do not update it\r\n if (doNotSetLineItemBidIfDirty && this.adjustments[matchingAdjustmentIndex].isDirty) {\r\n return;\r\n }\r\n\r\n const adjustmentsCopy = [...this.adjustments];\r\n\r\n let newAdjustmentToAddOrUpdate: Adjustment;\r\n\r\n if (mergeNewAdjustment) {\r\n newAdjustmentToAddOrUpdate = clone(adjustmentsCopy[matchingAdjustmentIndex]);\r\n newAdjustmentToAddOrUpdate.mergeExistingAdjustment(newAdjustment);\r\n } else {\r\n newAdjustmentToAddOrUpdate = clone(newAdjustment);\r\n }\r\n\r\n adjustmentsCopy[matchingAdjustmentIndex] = newAdjustmentToAddOrUpdate;\r\n this.adjustments = adjustmentsCopy;\r\n } else {\r\n this.adjustments = [...this.adjustments, clone(newAdjustment)];\r\n }\r\n }\r\n\r\n public deleteAdjustment(\r\n alternateId: string | null,\r\n bidderId: string,\r\n doNotSetLineItemBidIfDirty = false,\r\n ): void {\r\n const matchingAdjustmentIndex = this.adjustments.findIndex(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId) && v.bidderId === bidderId,\r\n );\r\n\r\n if (matchingAdjustmentIndex > -1) {\r\n // If the item we are about to update has unsaved changes for the current user, do not update it\r\n if (doNotSetLineItemBidIfDirty && this.adjustments[matchingAdjustmentIndex].isDirty) {\r\n return;\r\n }\r\n\r\n const adjustmentsCopy = [...this.adjustments];\r\n adjustmentsCopy.splice(matchingAdjustmentIndex, 1);\r\n this.adjustments = adjustmentsCopy;\r\n }\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Line Item Methods\r\n\r\n public getLineItems(alternateId: string | null): BidPackageLineItem[] {\r\n return this.lineItems.filter(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId),\r\n );\r\n }\r\n\r\n public getLineItemById(lineItemId: string): BidPackageLineItem | null {\r\n return this.lineItems?.find((v) => v.id === lineItemId) || null;\r\n }\r\n\r\n public setLineItem(lineItem: BidPackageLineItem): void {\r\n const existingLineItemIndex = this.lineItems.findIndex((v) => v.id === lineItem.id);\r\n\r\n const lineItemToAddOrUpdate = clone(lineItem);\r\n\r\n if (existingLineItemIndex > -1) {\r\n const lineItemsCopy = [...this.lineItems];\r\n lineItemsCopy[existingLineItemIndex] = lineItemToAddOrUpdate;\r\n this.lineItems = lineItemsCopy;\r\n } else {\r\n this.lineItems = [...this.lineItems, lineItemToAddOrUpdate];\r\n }\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Line Item Group Order Methods\r\n\r\n public getLineItemGroupOrders(alternateId: string | null): BidPackageLineItemGroupOrder[] {\r\n return this.lineItemGroupOrders.filter(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId),\r\n );\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Bidder Methods\r\n\r\n public getBidder(bidderId: string): Bidder | null {\r\n return this.bidders.find((v) => v.id === bidderId) || null;\r\n }\r\n\r\n public getBidderByCompanyName(companyName: string): Bidder | null {\r\n return (\r\n this.bidders.find((v) => areTrimmedStringsEqual(v.companyName || '', companyName)) || null\r\n );\r\n }\r\n\r\n public setSelectedBidder(bidderId: string): void {\r\n const matchingBidder = this.bidders.find((v) => v.id === bidderId);\r\n\r\n if (matchingBidder) {\r\n this.selectedBidderId = bidderId;\r\n this.selectedBidder = matchingBidder;\r\n }\r\n }\r\n\r\n public clearSelectedBidder(): void {\r\n this.selectedBidderId = undefined;\r\n this.selectedBidder = undefined;\r\n }\r\n\r\n public sortBidders(): void {\r\n this.bidders = sortBy(this.bidders, (b) => b.order);\r\n }\r\n\r\n public getBiddersSortedByBaseBidAmount(): Bidder[] {\r\n const bidders = orderBy(\r\n this.bidders,\r\n [\r\n (v) => (v.id === this.selectedBidderId ? 0 : 1),\r\n (v) => {\r\n const baseBidAmount = this.getBaseBidAmountInfoForBidder(\r\n v.id || '',\r\n null,\r\n ).total.toNumber();\r\n\r\n return baseBidAmount;\r\n },\r\n (v) => v.companyName?.toLowerCase(),\r\n ],\r\n ['asc', 'asc', 'asc'],\r\n );\r\n\r\n bidders.forEach((bidder, i) => {\r\n bidder.order = i;\r\n });\r\n\r\n return bidders;\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Requirements Methods\r\n\r\n public getRequirement(requirementId: string): BidPackageRequirement | null {\r\n return this.requirements.find((v) => v.id === requirementId) || null;\r\n }\r\n\r\n public getRequirementByDescription(\r\n isTradeRequirement: boolean,\r\n description: string,\r\n ): BidPackageRequirement | null {\r\n return (\r\n (isTradeRequirement\r\n ? BidPackage.getTradeRequirements(this.requirements)\r\n : BidPackage.getGeneralRequirements(this.requirements)\r\n ).find((v) => areTrimmedStringsEqual(v.description || '', description)) || null\r\n );\r\n }\r\n\r\n public getRequirementFulfillment(\r\n requirementId: string,\r\n bidderId: string,\r\n ): BidPackageRequirementFulfillment | null {\r\n const requirement = this.getRequirement(requirementId);\r\n return requirement?.requirementFulfillments?.find((v) => v.bidderId === bidderId) || null;\r\n }\r\n\r\n public setRequirementFulfillment(\r\n requirementId: string,\r\n newRequirementFulfillment: BidPackageRequirementFulfillment,\r\n doNotSetLineItemBidIfDirty = false,\r\n ): void {\r\n const requirementIndex = this.requirements.findIndex((v) => v.id === requirementId);\r\n\r\n if (requirementIndex > -1) {\r\n const requirementToUpdate = cloneDeep(this.requirements[requirementIndex]);\r\n\r\n const indexOfRequirementFulfillmentToUpdate = requirementToUpdate.requirementFulfillments.findIndex(\r\n (v) => v.bidderId === newRequirementFulfillment.bidderId,\r\n );\r\n\r\n const newRequirementFulfillmentToAddOrUpdate = clone(newRequirementFulfillment);\r\n\r\n if (indexOfRequirementFulfillmentToUpdate > -1) {\r\n // If the item we are about to update has unsaved changes for the current user, do not update it\r\n if (\r\n doNotSetLineItemBidIfDirty &&\r\n requirementToUpdate.requirementFulfillments[indexOfRequirementFulfillmentToUpdate].isDirty\r\n ) {\r\n return;\r\n }\r\n\r\n const fulfillmentsCopy = [...requirementToUpdate.requirementFulfillments];\r\n fulfillmentsCopy[\r\n indexOfRequirementFulfillmentToUpdate\r\n ] = newRequirementFulfillmentToAddOrUpdate;\r\n requirementToUpdate.requirementFulfillments = fulfillmentsCopy;\r\n } else {\r\n requirementToUpdate.requirementFulfillments = [\r\n ...requirementToUpdate.requirementFulfillments,\r\n newRequirementFulfillmentToAddOrUpdate,\r\n ];\r\n }\r\n\r\n const requirementsCopy = [...this.requirements];\r\n requirementsCopy[requirementIndex] = requirementToUpdate;\r\n this.requirements = requirementsCopy;\r\n }\r\n }\r\n\r\n public deleteRequirementFulfillment(\r\n requirementId: string,\r\n bidderId: string,\r\n doNotSetLineItemBidIfDirty = false,\r\n ): void {\r\n const requirementIndex = this.requirements.findIndex((v) => v.id === requirementId);\r\n\r\n if (requirementIndex > -1) {\r\n const newRequirementToAddOrUpdate = clone(this.requirements[requirementIndex]);\r\n\r\n const indexOfRequirementFulfillmentToDelete = newRequirementToAddOrUpdate.requirementFulfillments.findIndex(\r\n (v) => v.bidderId === bidderId,\r\n );\r\n\r\n if (indexOfRequirementFulfillmentToDelete > -1) {\r\n // If the item we are about to update has unsaved changes for the current user, do not update it\r\n if (\r\n doNotSetLineItemBidIfDirty &&\r\n newRequirementToAddOrUpdate.requirementFulfillments[indexOfRequirementFulfillmentToDelete]\r\n .isDirty\r\n ) {\r\n return;\r\n }\r\n\r\n const fulfillmentsCopy = [...newRequirementToAddOrUpdate.requirementFulfillments];\r\n fulfillmentsCopy.splice(indexOfRequirementFulfillmentToDelete, 1);\r\n newRequirementToAddOrUpdate.requirementFulfillments = fulfillmentsCopy;\r\n\r\n const requirementsCopy = [...this.requirements];\r\n requirementsCopy[requirementIndex] = newRequirementToAddOrUpdate;\r\n this.requirements = requirementsCopy;\r\n }\r\n }\r\n }\r\n\r\n // #endregion\r\n}\r\n","export class BidPackageContingencyAmount implements IODataResource {\r\n public readonly oDataResourceName = 'BidPackageContingencyAmount';\r\n\r\n public bidPackageId: string | undefined;\r\n public bidsTotal: number | undefined;\r\n public contingencyPercentage: number | undefined;\r\n public contingencyAmount: number | undefined;\r\n}\r\n","// NOTE: This class is intentionally not exposed directly via OData but\n// is able to be pulled back as an OData related entity\nexport class BidderFileUpload implements IODataResource {\n public readonly oDataResourceName = 'BidderFileUpload';\n\n public id: string | undefined;\n public bidderId: string | undefined;\n public fileName: string | undefined;\n public uploadDate: Date | undefined;\n\n public constructor(init?: Partial) {\n Object.assign(this, init);\n }\n}\n","import { plainToClass } from 'class-transformer';\r\nimport { AddBidderToBidPackageCommand } from '../../classes/commands/bid-packages/add-bidder-to-bid-package-command';\r\nimport { AddLineItemToBidPackageCommand } from '../../classes/commands/bid-packages/add-line-item-to-bid-package-command';\r\nimport { DeleteBidPackageLineItemCommand } from '../../classes/commands/bid-packages/delete-bid-package-line-item-command';\r\nimport { UpdateBidPackageBidderCommand } from '../../classes/commands/bid-packages/update-bid-package-bidder-command';\r\nimport { UpdateBidPackageLineItemCommand } from '../../classes/commands/bid-packages/update-bid-package-line-item-command';\r\nimport { BidPackage } from '../../classes/odata/bid-package';\r\nimport { BidPackageBidTotal } from '../../classes/odata/bid-package-bid-total';\r\nimport { BidPackageContingencyAmount } from '../../classes/odata/bid-package-contingency-amount';\r\nimport { BidderFileUpload } from '../../classes/odata/bidder-file-upload';\r\nimport { CommandHttpService } from '../command/command-http-service';\r\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\r\nimport { ODataHttpService } from '../odata/odata-http-service';\r\nimport { QueryHttpService } from '../query/query-http-service';\r\n\r\nconst getBidPackages = async (): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(BidPackage)\r\n .select('id', 'code', 'description')\r\n .getQueryObject();\r\n\r\n const result = await ODataHttpService.toArray(oDataQuery);\r\n return result as BidPackageInfo[];\r\n};\r\n\r\nconst getBidPackagesForProject = async (projectId: string): Promise => {\r\n if (!projectId) {\r\n return [];\r\n }\r\n const oDataQuery = new ODataQueryBuilder(BidPackage)\r\n .filter('projectId', 'equals', projectId)\r\n .select('id', 'code', 'description')\r\n .getQueryObject();\r\n\r\n const result = await ODataHttpService.toArray(oDataQuery);\r\n return result as BidPackageInfo[];\r\n};\r\n\r\nconst getBidPackageById = async (bidPackageId: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const bidPackageResult = await service.get(`bid-package/${bidPackageId}`);\r\n const bidPackage = plainToClass(BidPackage, bidPackageResult?.data);\r\n return bidPackage;\r\n};\r\n\r\nconst getBidPackageTotals = async (bidPackageId: string): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(BidPackageBidTotal)\r\n .filter('bidPackageId', 'equals', bidPackageId)\r\n .select('adjustmentAmount', 'alternateId', 'bidderId', 'bidsTotal')\r\n .getQueryObject();\r\n\r\n const result = await ODataHttpService.toArray(oDataQuery);\r\n return result;\r\n};\r\n\r\nconst getBidPackageContingencyAmounts = async (\r\n bidPackageIds: string[],\r\n): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const result = await service.get('/bid-packages-contingency-amounts', {\r\n params: {\r\n bidPackageIds: bidPackageIds,\r\n },\r\n });\r\n\r\n const contingencyAmounts = result.data.map((v: unknown) =>\r\n plainToClass(BidPackageContingencyAmount, v),\r\n );\r\n\r\n return contingencyAmounts;\r\n};\r\n\r\nconst addLineItemsToBidPackage = async (\r\n commands: AddLineItemToBidPackageCommand[],\r\n): Promise => {\r\n const service = await CommandHttpService.getCommandHttpService();\r\n await service.post('/bid-package/add-line-items', commands);\r\n};\r\n\r\nconst updateBidPackageLineItems = async (\r\n commands: UpdateBidPackageLineItemCommand[],\r\n): Promise => {\r\n const service = await CommandHttpService.getCommandHttpService();\r\n await service.post('/bid-package/update-line-items', commands);\r\n};\r\n\r\nconst deleteBidPackageLineItems = async (\r\n commands: DeleteBidPackageLineItemCommand[],\r\n): Promise => {\r\n const service = await CommandHttpService.getCommandHttpService();\r\n await service.post('/bid-package/delete-line-items', commands);\r\n};\r\n\r\nconst addBiddersToBidPackage = async (commands: AddBidderToBidPackageCommand[]): Promise => {\r\n const service = await CommandHttpService.getCommandHttpService();\r\n await service.post('/bid-package/add-bidders', commands);\r\n};\r\n\r\nconst updateBidPackageBidders = async (\r\n commands: UpdateBidPackageBidderCommand[],\r\n): Promise => {\r\n const service = await CommandHttpService.getCommandHttpService();\r\n await service.post('/bid-package/update-bidders', commands);\r\n};\r\n\r\nconst getBidderDocumentUploadUrl = (): string =>\r\n `${CommandHttpService.getApiUrl()}/bid-package/file-uploads/upload-bidder-document`;\r\n\r\nconst getBidderDocumentDownloadUrl = (\r\n projectId: string,\r\n bidPackageId: string,\r\n bidderCompanyName: string,\r\n fileName: string,\r\n): string => {\r\n return `${QueryHttpService.getApiUrl()}/project/${projectId}/bid-package/${bidPackageId}/bidder/${bidderCompanyName}/${fileName}`;\r\n};\r\n\r\nconst getBidderFileUploadsByBidPackageIdAndCompanyName = async (\r\n bidPackageId: string,\r\n companyName: string,\r\n): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const bidderFileUploadResults = await service.get(\r\n `/bid-package/${bidPackageId}/bidder/${companyName}/file-uploads`,\r\n );\r\n const fileUploads = bidderFileUploadResults.data.map((bfu) =>\r\n plainToClass(BidderFileUpload, bfu),\r\n );\r\n return fileUploads;\r\n};\r\n\r\nexport default {\r\n addBiddersToBidPackage,\r\n addLineItemsToBidPackage,\r\n deleteBidPackageLineItems,\r\n getBidPackageById,\r\n getBidPackageContingencyAmounts,\r\n getBidPackageTotals,\r\n getBidPackages,\r\n getBidPackagesForProject,\r\n getBidderDocumentDownloadUrl,\r\n getBidderDocumentUploadUrl,\r\n getBidderFileUploadsByBidPackageIdAndCompanyName,\r\n updateBidPackageBidders,\r\n updateBidPackageLineItems,\r\n};\r\n","export class Alternate implements IODataResource {\r\n public readonly oDataResourceName = 'Alternate';\r\n\r\n public enabled: boolean | undefined;\r\n public id: string | undefined;\r\n public name: string | undefined;\r\n public projectId: string | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n}\r\n","import { plainToClass } from 'class-transformer';\r\nimport { sortBy } from 'lodash';\r\nimport { Alternate } from '../../classes/odata/alternate';\r\nimport { BidPackage } from '../../classes/odata/bid-package';\r\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\r\nimport { ODataHttpService } from '../odata/odata-http-service';\r\nimport { QueryHttpService } from '../query/query-http-service';\r\n\r\nconst getBidPackagesByProjectId = async (projectId: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(`bid-package/summary?projectId=${projectId}`);\r\n let result = (response?.data.map((v) => plainToClass(BidPackage, v)) as unknown) as BidPackage[];\r\n\r\n // Sort the results\r\n result = sortBy(result, (v) => `${v.code} - ${v.description}`);\r\n return result;\r\n};\r\n\r\nconst getBidPackageTotals = async (bidPackageId: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(`bid-package/${bidPackageId}/totals`);\r\n return response?.data;\r\n};\r\n\r\nconst getAlternatesByProjectId = async (projectId: string): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(Alternate)\r\n .filter('projectId', 'equals', projectId)\r\n .select('id', 'name', 'enabled')\r\n\r\n .getQueryObject();\r\n\r\n const result = await ODataHttpService.toArray(oDataQuery);\r\n return result;\r\n};\r\n\r\nexport default { getBidPackagesByProjectId, getAlternatesByProjectId, getBidPackageTotals };\r\n","export class FeeDefinition implements IODataResource {\n public readonly oDataResourceName = 'FeeDefinition';\n\n public id: string | undefined;\n public name: string | undefined;\n public order: number | undefined;\n public feeType: number | undefined;\n public amount: number | undefined;\n public referenceFeeName: string | undefined;\n}\n","import { FeeDefinition } from '../../classes/odata/fee-definition';\nimport { CommandHttpService } from '../command/command-http-service';\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\nimport { ODataHttpService } from '../odata/odata-http-service';\nimport { QueryHttpService } from '../query/query-http-service';\n\n// Query Service API\nconst getFeeDefinitions = async (): Promise => {\n // lets create the data query builder to search for bid packages.\n const dataQueryBuilder = new ODataQueryBuilder(FeeDefinition);\n\n // now lets pull the data from the query service\n const oDataQuery = dataQueryBuilder.getQueryObject();\n const response = await ODataHttpService.toArray(oDataQuery);\n // NOTE: if the data that is selected changes, we need to make sure to update anywhere where we assume the data returned is not undefined\n return response;\n};\n\nconst calculateFeesForProject = async (projectId: string): Promise => {\n const service = await QueryHttpService.getQueryService();\n await service.post(`project/${projectId}/calculate-fees`);\n};\n\n// Command Service API\nconst calculateFeesForGrid = async (calculateFeesDTO: CalculateFeesDTO): Promise => {\n const service = await CommandHttpService.getCommandHttpService();\n const response = await service.post('fees/calculate-fees', calculateFeesDTO);\n return response.data;\n};\n\nexport default {\n getFeeDefinitions,\n calculateFeesForGrid,\n calculateFeesForProject,\n};\n","export class FrozenEntity implements IODataResource {\r\n public readonly oDataResourceName = 'FrozenEntity';\r\n\r\n public entityType: string | undefined;\r\n public entityId: string | undefined;\r\n public dateFrozen: Date | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n}\r\n","import { FrozenEntity } from '../../classes/odata/frozen-entity';\r\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\r\nimport { ODataHttpService } from '../odata/odata-http-service';\r\nimport { QueryHttpService } from '../query/query-http-service';\r\n\r\nconst checkIfEntityIsFrozen = async (entityId: string): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(FrozenEntity)\r\n .filter('entityId', 'equals', entityId)\r\n .count()\r\n .top(0)\r\n .getQueryObject();\r\n\r\n const itemCount = await ODataHttpService.getCount(oDataQuery);\r\n return itemCount > 0;\r\n};\r\n\r\nconst getAllFrozenEntities = async (): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(FrozenEntity).getQueryObject();\r\n\r\n return await ODataHttpService.toArray(oDataQuery);\r\n};\r\n\r\nconst getFrozenEntitiesListings = async (): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const result = await service.get('/frozen-entity-listings');\r\n return result.data;\r\n};\r\n\r\nconst syncEntity = async (entityId: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n await service.post(`/sync-entity?entityId=${entityId}`);\r\n};\r\n\r\nconst unfreezeEntity = async (entityId: string, entityType: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n await service.delete('/frozen-entity', {\r\n params: { entityId, entityType },\r\n });\r\n};\r\n\r\nexport default {\r\n checkIfEntityIsFrozen,\r\n getAllFrozenEntities,\r\n getFrozenEntitiesListings,\r\n syncEntity,\r\n unfreezeEntity,\r\n};\r\n","export class GeneralRequirementDefinition implements IODataResource {\r\n public readonly oDataResourceName = 'GeneralRequirementDefinition';\r\n\r\n public id: string | undefined;\r\n public index: number | undefined;\r\n public description: string | undefined;\r\n public requirementFulfillmentType: number | undefined;\r\n\r\n // Additional properties (client-side only)\r\n public isNew: boolean | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n}\r\n","import { GeneralRequirementDefinition } from '../../classes/odata/general-requirement-definition';\r\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\r\nimport { ODataHttpService } from '../odata/odata-http-service';\r\n\r\n// Query Service API\r\nconst getAllGeneralRequirementDefinitions = async (): Promise<\r\n GeneralRequirementDefinitionInterface[]\r\n> => {\r\n const oDataQuery = new ODataQueryBuilder(GeneralRequirementDefinition).getQueryObject();\r\n\r\n const definitions = await ODataHttpService.toArray(oDataQuery);\r\n return definitions.map(\r\n (d): GeneralRequirementDefinitionInterface => {\r\n return {\r\n description: d.description!,\r\n id: d.id!,\r\n index: d.index!,\r\n requirementFulfillmentType: d.requirementFulfillmentType!,\r\n isNew: false,\r\n };\r\n },\r\n );\r\n};\r\n\r\nexport default {\r\n getAllGeneralRequirementDefinitions,\r\n};\r\n","export class Preference implements IODataResource {\n public readonly oDataResourceName = 'Preference';\n\n public id!: string;\n public name!: string;\n public value: string | undefined;\n public projectId: string | undefined;\n}\n","const MeasurementSystemValues = {\n Imperial: 0,\n Metric: 1,\n};\n\nconst MeasurementSystemDisplayNames = {\n Imperial: 'Imperial',\n Metric: 'Metric',\n};\n\nexport { MeasurementSystemDisplayNames, MeasurementSystemValues };\n","import { MeasurementSystemDisplayNames, MeasurementSystemValues } from './measurement-systems';\n\nconst MeasurementSystems: MeasurementSystem[] = [\n {\n id: MeasurementSystemValues.Imperial,\n name: MeasurementSystemDisplayNames.Imperial,\n },\n {\n id: MeasurementSystemValues.Metric,\n name: MeasurementSystemDisplayNames.Metric,\n },\n];\n\nexport default MeasurementSystems;\n","import { Preference as PreferenceData } from '../../classes/odata/preferences';\nimport MeasurementSystems from '../../constants/preferences';\nimport { ODataHttpService } from '../odata/odata-http-service';\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\n\n// Massage the given data into the preferences object that the UI will work with\nconst preferencesFromData = (data: PreferenceData[]): Preferences => {\n // lets start with a new preferences object as the initial value\n const newPreferences: Preferences = {\n measurementSystem: MeasurementSystems[0],\n lowBiddersMax: 0,\n midBiddersMax: 1,\n };\n\n return data.reduce((obj, prefProp) => {\n // lets iterate through the properties on the given preferences to find the property who's name matches (doing this so this can be case insenstive).\n for (const propName in obj) {\n if (propName.toLowerCase() === prefProp.name.toLowerCase()) {\n // we found a matching property. Now lets convert the data if necessary\n if (\n propName.toLowerCase() === 'measurementsystem' &&\n Number(prefProp.value) !== undefined &&\n MeasurementSystems.find((x) => x.id === Number(prefProp.value)) !== undefined\n ) {\n // we are dealing with the measurement system property so we need to convert the number to the appropriate measure system\n obj[propName] = MeasurementSystems.find((x) => x.id === Number(prefProp.value))!;\n } else if (typeof obj[propName] === 'number' && !isNaN(Number(prefProp.value))) {\n obj[propName] = Number(prefProp.value);\n } else if (\n typeof obj[propName] === 'boolean' &&\n (prefProp.value?.toLowerCase() === 'true' || prefProp.value?.toLowerCase() === 'false')\n ) {\n obj[propName] = prefProp.value?.toLowerCase() === 'true' ? true : false;\n } else if (typeof obj[propName] === 'string' && prefProp.value !== undefined) {\n obj[propName] = prefProp.value;\n } else {\n throw new Error(\n `The value, ${prefProp.value}, for property, ${prefProp.name}, is invalid.`,\n );\n }\n break;\n }\n }\n return obj;\n }, newPreferences);\n};\n\n// Query Service API\n\nconst getPreferences = async (projectId: string | null = null): Promise => {\n const oDataQuery = new ODataQueryBuilder(PreferenceData)\n .filter('projectId', 'equals', projectId)\n .getQueryObject();\n const preferenceArrayData = await ODataHttpService.toArray(oDataQuery);\n const preferences = preferencesFromData(preferenceArrayData);\n return preferences;\n};\n\nexport default { getPreferences };\n","export class FeeCalculatedValues implements IODataResource {\r\n public readonly oDataResourceName = 'FeeCalculatedValues';\r\n\r\n public alternateId?: string | undefined;\r\n public calculatedContingencyValue: number | undefined;\r\n public calculatedValue: number | undefined;\r\n public feeId: string | undefined;\r\n public id: string | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n}\r\n","import React, { useCallback, useEffect, useRef } from 'react';\r\nimport { Observable, Subscription } from 'rxjs';\r\nimport { useObservableWithValue } from '../../../hooks/observables/useObservable';\r\n\r\nexport interface NotificationPanelMessage {\r\n title: string;\r\n message: string;\r\n type: NotificationPanelTypes;\r\n}\r\n\r\nexport enum NotificationPanelTypes {\r\n Success = 1,\r\n Error = 2,\r\n Info = 3,\r\n Warning = 4,\r\n}\r\n\r\ninterface NotificationPanelContextInterface {\r\n queuedNotifications$: Observable;\r\n setQueuedNotifications: (notifications: NotificationPanelMessage[]) => void;\r\n showErrorNotification: (title: string, message: string) => void;\r\n showInfoNotification: (title: string, message: string) => void;\r\n showSuccessNotification: (title: string, message: string) => void;\r\n showWarningNotification: (title: string, message: string) => void;\r\n}\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nconst NotificationPanelContext = React.createContext(\r\n {} as NotificationPanelContextInterface,\r\n);\r\n\r\nconst NotificationPanelContextProvider: React.FC = (props) => {\r\n const queuedNotificationsCurrValue = useRef([]);\r\n\r\n const [queuedNotifications$, setQueuedNotifications] = useObservableWithValue<\r\n NotificationPanelMessage[]\r\n >();\r\n\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n queuedNotifications$.subscribe((data) => {\r\n queuedNotificationsCurrValue.current = [...data];\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [queuedNotifications$]);\r\n\r\n const addNotificationToQueue = useCallback(\r\n (title: string, message: string, type: NotificationPanelTypes): void => {\r\n // Use the state updater callback pattern so we don't have any dependencies for useCallback.\r\n // Do not allow duplicate messages.\r\n if (\r\n queuedNotificationsCurrValue.current.some(\r\n (v) => v.type === type && v.title === title && v.message === message,\r\n )\r\n ) {\r\n return;\r\n }\r\n\r\n const newValue = [\r\n ...queuedNotificationsCurrValue.current,\r\n {\r\n title: title,\r\n message: message,\r\n type: type,\r\n },\r\n ];\r\n\r\n setQueuedNotifications(newValue);\r\n },\r\n [setQueuedNotifications],\r\n );\r\n\r\n const showSuccessNotification = useCallback(\r\n (title: string, message: string): void => {\r\n addNotificationToQueue(title, message, NotificationPanelTypes.Success);\r\n },\r\n [addNotificationToQueue],\r\n );\r\n\r\n const showErrorNotification = useCallback(\r\n (title: string, message: string): void => {\r\n addNotificationToQueue(title, message, NotificationPanelTypes.Error);\r\n },\r\n [addNotificationToQueue],\r\n );\r\n\r\n const showInfoNotification = useCallback(\r\n (title: string, message: string): void => {\r\n addNotificationToQueue(title, message, NotificationPanelTypes.Info);\r\n },\r\n [addNotificationToQueue],\r\n );\r\n\r\n const showWarningNotification = useCallback(\r\n (title: string, message: string): void => {\r\n addNotificationToQueue(title, message, NotificationPanelTypes.Warning);\r\n },\r\n [addNotificationToQueue],\r\n );\r\n\r\n return (\r\n <>\r\n \r\n {props.children}\r\n \r\n \r\n );\r\n};\r\n\r\nexport { NotificationPanelContext, NotificationPanelContextProvider };\r\n","import { Type } from 'class-transformer';\r\nimport { FeeTypes } from '../../app/enums/fee-enum';\r\nimport { areTrimmedStringsEqual } from '../../utils/strings';\r\nimport { FeeCalculatedValues } from './fee-calculated-values';\r\n\r\nexport class Fee implements IODataResource {\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n public readonly oDataResourceName = 'Fee';\r\n\r\n public amount: number | undefined;\r\n public feeType: number | undefined;\r\n public id: string | undefined;\r\n public name: string | undefined;\r\n public order: number | undefined;\r\n public projectId: string | undefined;\r\n public referenceFeeName: string | undefined;\r\n\r\n @Type(() => FeeCalculatedValues)\r\n public calculatedValues: FeeCalculatedValues[] = [];\r\n\r\n // Recursively finds the last referenced fee for the fee is a \"percent\" of another fee\r\n public static getLastReferencedFeeForPercentFee(currFee: Fee, allFees: Fee[], counter = 0): Fee {\r\n if (currFee.feeType !== FeeTypes.Percent || !currFee.referenceFeeName || counter > 50) {\r\n return currFee;\r\n }\r\n\r\n const matchingFee = allFees.find((v) => {\r\n return areTrimmedStringsEqual(currFee.referenceFeeName, v.name);\r\n });\r\n\r\n if (matchingFee) {\r\n return Fee.getLastReferencedFeeForPercentFee(matchingFee, allFees, counter + 1);\r\n }\r\n\r\n return currFee;\r\n }\r\n}\r\n","import Big from 'big.js';\r\nimport { Type } from 'class-transformer';\r\nimport { Alternate } from './alternate';\r\nimport { BidPackage } from './bid-package';\r\nimport { Fee } from './fee';\r\n\r\nexport class Project implements IODataResource {\r\n public readonly oDataResourceName = 'Project';\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n\r\n public architect: string | undefined;\r\n public bidDueDate: Date | undefined;\r\n public dateCreated: Date | undefined;\r\n public completionDate: Date | undefined;\r\n public contributors: string | undefined;\r\n public fileUploadContainerId: string | undefined;\r\n public id: string | undefined;\r\n public imageUri: string | undefined;\r\n public isHardBid: boolean | undefined;\r\n public isClosed: boolean | undefined;\r\n public lineItemRollup1: string | undefined;\r\n public lineItemRollup2: string | undefined;\r\n public name: string | undefined;\r\n public notes: string | undefined;\r\n public notesId: string | undefined;\r\n public owner: string | undefined;\r\n public projectAdmins: string | undefined;\r\n public siteAddress: Address | undefined;\r\n public startDate: Date | undefined;\r\n public subtitle: string | undefined;\r\n public totalBuildingArea: number | undefined;\r\n public totalBuildingAreaUnitOfMeasure: string | undefined;\r\n public totalSiteArea: number | undefined;\r\n public totalSiteAreaUnitOfMeasure: string | undefined;\r\n public hasFeeCalculationFailure: boolean | undefined;\r\n\r\n public get streetAddress(): string {\r\n return this.siteAddress?.streetAddress || '';\r\n }\r\n\r\n public get city(): string {\r\n return this.siteAddress?.city || '';\r\n }\r\n\r\n public get state(): string {\r\n return this.siteAddress?.stateOrRegion || '';\r\n }\r\n\r\n public get postalCode(): string {\r\n return this.siteAddress?.postalCode || '';\r\n }\r\n\r\n @Type(() => BidPackage)\r\n public bidPackages: BidPackage[] = [];\r\n\r\n @Type(() => Alternate)\r\n public alternates: Alternate[] = [];\r\n\r\n @Type(() => Fee)\r\n public fees: Fee[] = [];\r\n\r\n // sums base estimate amount/bid amounts for selected bidders for all bid packages.\r\n // passing in parameter so we're not relying on the one in the project object, in case it's not wired up.\r\n public static calculateBaseEstimateAmount(bidPackages: BidPackage[]): Big {\r\n let baseEstimateAmount = new Big(0);\r\n bidPackages.forEach((bp) => {\r\n let bpTotal: { total: Big; adjustmentAmount: Big } | null;\r\n if (bp.isGeneralCondition) {\r\n // For the general conditions bid package, the bid total is the base estimate amount\r\n bpTotal = {\r\n total: new Big(bp.getBaseEstimateAmount(null)?.total ?? 0),\r\n adjustmentAmount: new Big(0),\r\n };\r\n } else {\r\n bpTotal = bp.selectedBidderId\r\n ? bp.getBaseBidAmountInfoForBidder(bp.selectedBidderId, null)\r\n : null;\r\n }\r\n\r\n if (bpTotal) {\r\n baseEstimateAmount = baseEstimateAmount.add(bpTotal.total);\r\n }\r\n });\r\n\r\n return baseEstimateAmount;\r\n }\r\n\r\n // sums alternate amounts for all bid packages and a given alternate.\r\n // passing in parameters so we're not relying on the ones in the project object, in case they're not wired up.\r\n public static calculateAlternateAmountForAllBidPackages(\r\n bidPackages: BidPackage[],\r\n alternate: Alternate,\r\n ): Big {\r\n let total = new Big(0);\r\n\r\n if (alternate?.enabled) {\r\n bidPackages?.forEach((bp) => {\r\n if (bp.isGeneralCondition) {\r\n total = total.add(bp.getBaseEstimateAmount(alternate?.id ?? null)?.total ?? 0);\r\n } else {\r\n if (bp.selectedBidderId) {\r\n total = total.add(\r\n bp.getBaseBidAmountInfoForBidder(bp.selectedBidderId, alternate?.id || null).total,\r\n );\r\n }\r\n }\r\n });\r\n }\r\n return total;\r\n }\r\n\r\n // sums all contingency amounts for bid packages of a project.\r\n // passing in parameters so we're not relying on the ones in the project object, in case they're not wired up.\r\n public static calculateContingencyAmountForAllBidPackages(bidPackages: BidPackage[]): Big {\r\n let total = new Big(0);\r\n\r\n bidPackages?.forEach((bp) => {\r\n // NOTE: Each bid package should have its related contingency amount entity loaded\r\n total = total.add(bp.contingencyAmount?.contingencyAmount ?? 0);\r\n });\r\n\r\n return total;\r\n }\r\n\r\n // sums base estimate amount, (enabled) alternate amounts for all bid packages, and contingencies for all bid packages.\r\n // passing in parameters so we're not relying on the ones in the project object, in case they're not wired up.\r\n public static calculateProjectBidTotal(\r\n bidPackages: BidPackage[],\r\n alternates: Alternate[],\r\n ): number {\r\n let total = new Big(this.calculateBaseEstimateAmount(bidPackages));\r\n\r\n // NOTE: The calculateAlternateAmountForAllBidPackages() method handles checking if the alternate is enabled\r\n alternates.forEach((a) => {\r\n total = total.add(this.calculateAlternateAmountForAllBidPackages(bidPackages, a));\r\n });\r\n\r\n return total.add(this.calculateContingencyAmountForAllBidPackages(bidPackages)).toNumber();\r\n }\r\n\r\n public getAddressText(): string {\r\n if (!this.siteAddress) {\r\n return '';\r\n }\r\n\r\n const parts: string[] = [];\r\n\r\n if (this.siteAddress.streetAddress) {\r\n const streetAddress = `${this.siteAddress.streetAddress}${\r\n ' ' + this.siteAddress.aptSuiteBldg || ''\r\n }`;\r\n parts.push(streetAddress);\r\n }\r\n\r\n if (this.siteAddress.city) {\r\n parts.push(this.siteAddress.city);\r\n }\r\n\r\n if (this.siteAddress.stateOrRegion) {\r\n parts.push(this.siteAddress.stateOrRegion);\r\n }\r\n\r\n if (this.siteAddress.postalCode) {\r\n parts.push(this.siteAddress.postalCode);\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n","import FileSaver from 'file-saver';\r\nimport { sortBy } from 'lodash';\r\nimport { BidPackage } from '../../classes/odata/bid-package';\r\nimport { Fee } from '../../classes/odata/fee';\r\nimport { FeeCalculatedValues } from '../../classes/odata/fee-calculated-values';\r\nimport { Project } from '../../classes/odata/project';\r\nimport { CommandHttpService } from '../command/command-http-service';\r\nimport { ODataQueryBuilder, ODataQueryFilter } from '../odata/bt-odata-service';\r\nimport { ODataHttpService } from '../odata/odata-http-service';\r\nimport { QueryHttpService } from '../query/query-http-service';\r\n\r\nconst commandServiceUrl = CommandHttpService.getApiUrl();\r\n\r\nconst getProjectInfoById = async (id: string): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(Project)\r\n .filter('id', 'equals', id)\r\n .select(\r\n 'architect',\r\n 'bidDueDate',\r\n 'completionDate',\r\n 'contributors',\r\n 'fileUploadContainerId',\r\n 'id',\r\n 'imageUri',\r\n 'isClosed',\r\n 'isHardBid',\r\n 'name',\r\n 'owner',\r\n 'projectAdmins',\r\n 'siteAddress',\r\n 'startDate',\r\n 'subtitle',\r\n 'totalBuildingArea',\r\n 'totalBuildingAreaUnitOfMeasure',\r\n 'totalSiteArea',\r\n 'totalSiteAreaUnitOfMeasure',\r\n 'hasFeeCalculationFailure',\r\n 'notes',\r\n 'notesId',\r\n )\r\n .getQueryObject();\r\n\r\n let response = await ODataHttpService.firstOrDefault(oDataQuery);\r\n\r\n if (response) {\r\n // tweak some properties before we return the response.\r\n response = {\r\n ...response,\r\n contributors: response!.contributors?.toLowerCase() ?? null,\r\n projectAdmins: response!.projectAdmins?.toLowerCase() ?? null,\r\n };\r\n }\r\n return response;\r\n};\r\n\r\nconst getBidPackagesByProjectId = async (id: string): Promise => {\r\n if (!id) {\r\n return [];\r\n }\r\n const oDataQuery = new ODataQueryBuilder(BidPackage)\r\n .filter('projectId', 'equals', id)\r\n .select('id', 'code', 'description', 'assignedToUserId', 'requirements')\r\n .expand('requirements')\r\n .getQueryObject();\r\n\r\n const result = await ODataHttpService.toArray(oDataQuery);\r\n return result;\r\n};\r\n\r\nconst getAlternatesByProjectId = async (id: string): Promise => {\r\n if (!id) {\r\n return [];\r\n }\r\n\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(`/projects/${id}/alternates`);\r\n return response.data || [];\r\n};\r\n\r\nconst getFeesByProjectId = async (id: string): Promise => {\r\n if (!id) {\r\n return [];\r\n }\r\n const oDataQuery = new ODataQueryBuilder(Fee)\r\n .filter('projectId', 'equals', id)\r\n .select('id', 'name', 'order', 'amount', 'feeType', 'referenceFeeName')\r\n .getQueryObject();\r\n\r\n const result = await ODataHttpService.toArray(oDataQuery);\r\n return result as ProjectFee[];\r\n};\r\n\r\nconst getAllProjectInfos = async (): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(Project)\r\n .select('id', 'name', 'subtitle', 'bidDueDate', 'projectAdmins')\r\n .getQueryObject();\r\n\r\n let response = await ODataHttpService.toArray(oDataQuery);\r\n\r\n // Sort the projects and tweak some properties before we return the response.\r\n response = sortBy(response, (v) => v.name).map((currentProjectInfo) => {\r\n return {\r\n ...currentProjectInfo,\r\n contributors: currentProjectInfo.contributors?.toLowerCase() ?? null,\r\n projectAdmins: currentProjectInfo.projectAdmins?.toLowerCase() ?? null,\r\n };\r\n });\r\n\r\n return response;\r\n};\r\n\r\nconst getProjectCount = async (): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(Project).count().top(0).getQueryObject();\r\n const itemCount = await ODataHttpService.getCount(oDataQuery);\r\n return itemCount;\r\n};\r\n\r\nconst getFeesAndTotalsByProjectId = async (projectId: string): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(Fee)\r\n .filter('projectId', 'equals', projectId)\r\n .expand('calculatedValues')\r\n .select(\r\n 'alternateId',\r\n 'calculatedValue',\r\n 'calculatedContingencyValue',\r\n 'feeId',\r\n 'id',\r\n )\r\n .getQueryObject();\r\n\r\n let response = await ODataHttpService.toArray(oDataQuery);\r\n\r\n // Sort the fees\r\n response = sortBy(response, (v) => v.name);\r\n\r\n return response;\r\n};\r\n\r\nconst getProjectInfoForBidPackage = async (bidPackageId: string): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(Project)\r\n .filter('bidPackages', 'any', {\r\n propertyName: 'id',\r\n type: 'equals',\r\n value: bidPackageId,\r\n } as ODataQueryFilter)\r\n .select(\r\n 'bidDueDate',\r\n 'contributors',\r\n 'id',\r\n 'imageUri',\r\n 'isClosed',\r\n 'lineItemRollup1',\r\n 'lineItemRollup2',\r\n 'name',\r\n 'projectAdmins',\r\n 'subtitle',\r\n )\r\n .expand('alternates')\r\n .getQueryObject();\r\n\r\n let response = await ODataHttpService.firstOrDefault(oDataQuery);\r\n\r\n // tweak some properties before we return the response.\r\n if (response) {\r\n response = new Project({\r\n ...response!,\r\n projectAdmins: response!.projectAdmins?.toLowerCase() ?? undefined,\r\n });\r\n }\r\n return response;\r\n};\r\n\r\nconst getLineItemMetadataForProject = async (projectId: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(`/projects/${projectId}/metadata`);\r\n if (response.data) {\r\n return response.data;\r\n }\r\n return [];\r\n};\r\n\r\nconst getProjectImageUploadUrl = (): string => {\r\n return `${commandServiceUrl}/project/file-uploads/upload-project-document`;\r\n};\r\n\r\nconst getProjectImageBlobUrl = async (projectId: string, fileName: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(`/project/${projectId}/${fileName}`, {\r\n responseType: 'blob',\r\n });\r\n\r\n // NOTE: Since the url may be set to backgroundImage property, the url does not get encoded\r\n // by default (like it would in a \"src\" property of an img tag) so we have to encode things like\r\n // spaces ourselves\r\n const blobUrl = URL.createObjectURL(response.data).replace(/ /g, encodeURIComponent(' '));\r\n return blobUrl;\r\n};\r\n\r\n// The date range is the number of days to go back\r\nconst searchAllProjects = async (\r\n dateRange: number,\r\n searchText: string,\r\n): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(\r\n `/search-projects/${dateRange}/${searchText}`,\r\n );\r\n if (response.data) {\r\n let searchResults = response.data;\r\n\r\n // tweak some properties before we return the response.\r\n searchResults = searchResults.map((currentResult) => {\r\n return {\r\n ...currentResult,\r\n projectAdmins: currentResult!.projectAdmins?.toLowerCase() ?? null,\r\n };\r\n });\r\n return searchResults;\r\n }\r\n return [];\r\n};\r\n\r\nconst exportProjectToExcel = async (projectId: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(`/export/project/${projectId}`, { responseType: 'blob' });\r\n if (response.data) {\r\n let filename = `${projectId}.xlsx`;\r\n const disposition: string = response.headers['content-disposition'];\r\n if (disposition && disposition.indexOf('attachment') !== -1) {\r\n const filenameRegex = /filename[^;=\\n]*=((['\"]).*?\\2|[^;\\n]*)/;\r\n const matches = filenameRegex.exec(disposition);\r\n if (matches != null && matches[1]) {\r\n filename = matches[1].replace(/['\"]/g, '');\r\n }\r\n }\r\n FileSaver.saveAs(response.data, filename);\r\n }\r\n};\r\n\r\nexport default {\r\n exportProjectToExcel,\r\n getAllProjectInfos,\r\n getAlternatesByProjectId,\r\n getBidPackagesByProjectId,\r\n getFeesAndTotalsByProjectId,\r\n getFeesByProjectId,\r\n getLineItemMetadataForProject,\r\n getProjectCount,\r\n getProjectImageUploadUrl,\r\n getProjectImageBlobUrl,\r\n getProjectInfoById,\r\n getProjectInfoForBidPackage,\r\n searchAllProjects,\r\n};\r\n","import { AuthenticationService } from '../authentication/authentication-service';\r\nimport { QueryHttpService } from '../query/query-http-service';\r\n\r\n// Query Service API\r\n\r\n// The date range is the number of days to go back\r\nconst getRecentProjectsForUser = async (): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get('/recent-projects');\r\n if (response.data) {\r\n const searchResults = response?.data;\r\n return searchResults;\r\n }\r\n return [];\r\n};\r\n\r\nconst addRecentProject = async (projectId: string): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n const recentProject = {\r\n email: AuthenticationService.currentUserInfo!.email,\r\n projectId: projectId,\r\n };\r\n await service.post('/recent-projects', recentProject);\r\n};\r\n\r\nexport default { getRecentProjectsForUser, addRecentProject };\r\n","export class ProjectViewSetting implements IODataResource {\r\n public readonly oDataResourceName: string;\r\n\r\n constructor(oDataResourceName?: string) {\r\n this.oDataResourceName = oDataResourceName ?? 'ProjectViewSetting';\r\n }\r\n\r\n public groupingKey1: string | undefined;\r\n public groupingKey2: string | undefined;\r\n public id: string | undefined;\r\n public userId: string | undefined;\r\n}\r\n","import { ProjectViewSetting } from './project-view-setting';\r\n\r\nexport class AllProjectViewSetting extends ProjectViewSetting implements IODataResource {\r\n constructor() {\r\n super('AllProjectViewSetting');\r\n }\r\n\r\n public dateRange: number | undefined;\r\n}\r\n","import { AllProjectViewSetting } from '../../classes/odata/all-project-view-setting';\r\nimport { ProjectViewSetting } from '../../classes/odata/project-view-setting';\r\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\r\nimport { ODataHttpService } from '../odata/odata-http-service';\r\nimport { QueryHttpService } from '../query/query-http-service';\r\n\r\n// Query Service API\r\n\r\nconst getProjectViewSettings_Recent = async (\r\n userId: string,\r\n): Promise => {\r\n // NOTE: The OData endpoint is set up to limit the results to the current user's user ID\r\n const oDataQuery = new ODataQueryBuilder(ProjectViewSetting)\r\n .filter('userId', 'equals', userId)\r\n .select('groupingKey1', 'groupingKey2')\r\n .getQueryObject();\r\n\r\n const result = await ODataHttpService.firstOrDefault(oDataQuery);\r\n return result;\r\n};\r\n\r\nconst getProjectViewSettings_All = async (\r\n userId: string,\r\n): Promise => {\r\n // NOTE: The OData endpoint is set up to limit the results to the current user's user ID\r\n const oDataQuery = new ODataQueryBuilder(AllProjectViewSetting)\r\n .filter('userId', 'equals', userId)\r\n .select('groupingKey1', 'groupingKey2', 'dateRange')\r\n .getQueryObject();\r\n\r\n const result = await ODataHttpService.firstOrDefault(oDataQuery);\r\n return result;\r\n};\r\n\r\nconst updateProjectViewSettings = async (settings: UpdateProjectViewSettings): Promise => {\r\n const service = await QueryHttpService.getQueryService();\r\n return await service.post(`/settings/update-project-view-settings`, settings);\r\n};\r\n\r\nexport default {\r\n getProjectViewSettings_Recent,\r\n getProjectViewSettings_All,\r\n updateProjectViewSettings,\r\n};\r\n","export class SystemValue implements IODataResource {\r\n public readonly oDataResourceName = 'SystemValue';\r\n\r\n public name: string | undefined;\r\n public value: string | undefined;\r\n}\r\n","import { SystemValue as SystemValueData } from '../../classes/odata/system-value';\r\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\r\nimport { ODataHttpService } from '../odata/odata-http-service';\r\n\r\n// Query Service API\r\nconst getSystemValue = async (systemValueName: string): Promise => {\r\n const oDataQuery = new ODataQueryBuilder(SystemValueData)\r\n .filter('name', 'equals', systemValueName)\r\n .getQueryObject();\r\n const systemValueData = await ODataHttpService.firstOrDefault(oDataQuery);\r\n return systemValueData?.value || null;\r\n};\r\n\r\nexport default {\r\n getSystemValue,\r\n};\r\n","export class UnitOfMeasure implements IODataResource {\r\n public readonly oDataResourceName = 'UnitOfMeasure';\r\n\r\n public name: string | undefined;\r\n\r\n public constructor(init?: Partial) {\r\n Object.assign(this, init);\r\n }\r\n}\r\n","import { UnitOfMeasure } from '../../classes/odata/unit-of-measure';\nimport { ODataQueryBuilder } from '../odata/bt-odata-service';\nimport { ODataHttpService } from '../odata/odata-http-service';\nimport { QueryHttpService } from '../query/query-http-service';\n\n// Query Service API\n\nconst getAllUnitsOfMeasure = async (): Promise => {\n const oDataQuery = new ODataQueryBuilder(UnitOfMeasure).getQueryObject();\n return await ODataHttpService.toArray(oDataQuery);\n};\n\nconst addUnitOfMeasure = async (unitOfMeasure: UnitOfMeasure): Promise => {\n const service = await QueryHttpService.getQueryService();\n const response = await service.post('/units-of-measure', unitOfMeasure);\n\n if (!response.data) {\n return null;\n }\n\n return response.data;\n};\n\nconst deleteUnitOfMeasure = async (unitOfMeasure: UnitOfMeasure): Promise => {\n const service = await QueryHttpService.getQueryService();\n await service.delete('/units-of-measure', {\n params: { unitOfMeasureName: unitOfMeasure.name },\n });\n};\n\nexport default { getAllUnitsOfMeasure, addUnitOfMeasure, deleteUnitOfMeasure };\n","import { CommandBase } from './CommandBase';\r\n\r\nexport abstract class CommandBatchBase extends CommandBase implements IBatchCommand {\r\n private readonly allCommands: ICommand[] = [];\r\n\r\n public readonly allowedCommandClassTypes: Ctor[] = [];\r\n\r\n constructor(\r\n type: string,\r\n apiUrl: string,\r\n httpMethod: HttpMethods,\r\n allowedCommandClassTypes: Ctor[],\r\n ) {\r\n super(type, apiUrl, httpMethod);\r\n\r\n this.allowedCommandClassTypes = allowedCommandClassTypes;\r\n }\r\n\r\n public getCommands(): ICommand[] {\r\n return this.allCommands;\r\n }\r\n\r\n public setCommands(value: ICommand[]): T {\r\n this.validateCommandTypes(...value);\r\n this.allCommands.splice(0, this.allCommands.length, ...value);\r\n return (this as unknown) as T;\r\n }\r\n\r\n public addCommand(commandObj: ICommand): T {\r\n this.validateCommandTypes(commandObj);\r\n\r\n this.allCommands.push(commandObj);\r\n\r\n return (this as unknown) as T;\r\n }\r\n\r\n public clearCommands(): T {\r\n this.allCommands.splice(0, this.allCommands.length);\r\n return (this as unknown) as T;\r\n }\r\n\r\n public generateRequestData(): unknown {\r\n return this.allCommands.map((v) => v.generateRequestData());\r\n }\r\n\r\n private validateCommandTypes(...commandObjects: ICommand[]): void {\r\n commandObjects.forEach((currCommandObj) => {\r\n if (!this.allowedCommandClassTypes.some((v) => currCommandObj instanceof v)) {\r\n throw new Error(`Unsupported command class type: '${currCommandObj.constructor.name}'`);\r\n }\r\n });\r\n }\r\n}\r\n","import { AxiosResponse } from 'axios';\r\nimport { cloneDeep } from 'lodash';\r\nimport { CommandBase } from '../../classes/commands/CommandBase';\r\nimport { CommandBatchBase } from '../../classes/commands/CommandBatchBase';\r\nimport { nameof } from '../../utils/nameof';\r\nimport { CommandHttpService } from './command-http-service';\r\n\r\nexport class CommandManagerService implements ICommandManager {\r\n private allCommands: ICommand[] = [];\r\n\r\n public clone(): CommandManagerService {\r\n return cloneDeep(this);\r\n }\r\n\r\n public getCommands(): ICommand[] {\r\n return this.allCommands;\r\n }\r\n\r\n public setCommands(commandObjects: ICommand[]): T {\r\n this.allCommands = commandObjects;\r\n return (this as unknown) as T;\r\n }\r\n\r\n public addCommand(...commandObj: ICommand[]): T {\r\n this.allCommands.push(...commandObj);\r\n return (this as unknown) as T;\r\n }\r\n\r\n public clearCommands(): T {\r\n this.allCommands.splice(0, this.allCommands.length);\r\n return (this as unknown) as T;\r\n }\r\n\r\n // Executes a single command, starting from the beginning of the array\r\n public async executeNextCommand(): Promise {\r\n if (!this.allCommands.length) {\r\n return null;\r\n }\r\n\r\n const commandToExecute = this.allCommands.shift() as ICommand;\r\n return await CommandManagerService.executeCommand(commandToExecute);\r\n\r\n // TODO - in the future, we will want this method to update the status of the\r\n // command based on the result of the ajax call, etc.\r\n }\r\n\r\n public static async executeCommand(commandToExecute: ICommand): Promise {\r\n const httpService = await CommandHttpService.getCommandHttpService();\r\n\r\n // NOTE: Since commands and batch commands both implement ICommand, we can call the methods to\r\n // generate the URL / request data without doing anything special\r\n const url = commandToExecute.apiUrl!;\r\n const requestData = commandToExecute.generateRequestData();\r\n\r\n // If the command is not a batch command, we want to remove the type property before sending\r\n // the command to the server, since it won't be used and will save a little bit of data\r\n if (!(commandToExecute instanceof CommandBatchBase)) {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n delete (requestData as any)[nameof('__type')];\r\n }\r\n\r\n let response: AxiosResponse;\r\n\r\n try {\r\n switch (commandToExecute?.httpMethod) {\r\n case 'put':\r\n response = await httpService.put(url, requestData);\r\n break;\r\n\r\n case 'post':\r\n response = await httpService.post(url, requestData);\r\n break;\r\n\r\n case 'delete':\r\n response = await httpService.delete(url);\r\n break;\r\n\r\n default:\r\n throw new Error('Invalid HTTP method on command');\r\n }\r\n\r\n return response;\r\n } catch (errorObj) {\r\n throw errorObj;\r\n }\r\n }\r\n}\r\n","import React, { useContext } from 'react';\nimport { ReactPlugin } from '@microsoft/applicationinsights-react-js';\nimport { SeverityLevel } from '@microsoft/applicationinsights-web';\n\ninterface ProviderProps {\n appInsightsPlugin: ReactPlugin | undefined;\n}\n\nexport class Logger {\n constructor(private appInsightsPlugin?: ReactPlugin) {}\n\n public logDebug(...msgs: unknown[]): void {\n window.log.debug(...msgs);\n }\n\n public logWarning(...msgs: unknown[]): void {\n window.log.warn(...msgs);\n }\n\n public logError(error: unknown): void {\n window.log.error(error);\n this.appInsightsPlugin?.trackException({\n exception: error instanceof Error ? error : new Error(`${error}`),\n severityLevel: SeverityLevel.Error,\n });\n }\n}\n\nconst LoggingContext = React.createContext({} as Logger);\n\nexport const useLogger = (): Logger => useContext(LoggingContext);\n\nexport const LoggingContextProvider: React.FC = (props) => {\n const { appInsightsPlugin } = props;\n const logger = new Logger(appInsightsPlugin);\n return {props.children};\n};\n","import React, { useCallback, useRef } from 'react';\r\nimport { Observable } from 'rxjs';\r\nimport { useObservableWithValue } from '../../../hooks/observables/useObservable';\r\n\r\nexport interface FloatingIndicatorDisplayInfo {\r\n text: string;\r\n // We keep track of how many times the indicator has been turned on / off so things don't get\r\n // turned off prematurely\r\n counter: number;\r\n}\r\n\r\ninterface FloatingLoadingIndicatorContextInterface {\r\n floatingLoadingIndicatorDisplayInfo_Blue$: Observable;\r\n floatingLoadingIndicatorDisplayInfo_Green$: Observable;\r\n\r\n showFloatingLoadingIndicator_Blue: (text: string) => void;\r\n showFloatingLoadingIndicator_Green: (text: string) => void;\r\n\r\n hideFloatingLoadingIndicator_Green: () => void;\r\n hideFloatingLoadingIndicator_Blue: () => void;\r\n}\r\n\r\nconst FloatingLoadingIndicatorContext = React.createContext<\r\n FloatingLoadingIndicatorContextInterface\r\n>({} as FloatingLoadingIndicatorContextInterface);\r\n\r\nconst FloatingLoadingIndicatorContextProvider: React.FC = (props) => {\r\n const previousValue_DisplayInfo_Blue = useRef({\r\n text: '',\r\n counter: 0,\r\n });\r\n\r\n const previousValue_DisplayInfo_Green = useRef({\r\n text: '',\r\n counter: 0,\r\n });\r\n\r\n const [displayInfo_Blue$, setDisplayInfo_Blue] = useObservableWithValue<\r\n FloatingIndicatorDisplayInfo\r\n >();\r\n\r\n const [displayInfo_Green$, setDisplayInfo_Green] = useObservableWithValue<\r\n FloatingIndicatorDisplayInfo\r\n >();\r\n\r\n const showFloatingLoadingIndicator_Blue = useCallback(\r\n (text: string): void => {\r\n const newValue: FloatingIndicatorDisplayInfo = {\r\n text,\r\n counter: previousValue_DisplayInfo_Blue.current.counter + 1,\r\n };\r\n\r\n setDisplayInfo_Blue(newValue);\r\n\r\n previousValue_DisplayInfo_Blue.current = { ...newValue };\r\n },\r\n [setDisplayInfo_Blue],\r\n );\r\n\r\n const hideFloatingLoadingIndicator_Blue = useCallback((): void => {\r\n const newValue: FloatingIndicatorDisplayInfo = {\r\n text: previousValue_DisplayInfo_Blue.current.text, // Keep the text the same when we hide things so it doesn't flicker in the UI\r\n counter: previousValue_DisplayInfo_Blue.current.counter - 1,\r\n };\r\n\r\n setDisplayInfo_Blue(newValue);\r\n\r\n previousValue_DisplayInfo_Blue.current = { ...newValue };\r\n }, [setDisplayInfo_Blue]);\r\n\r\n const showFloatingLoadingIndicator_Green = useCallback(\r\n (text: string): void => {\r\n const newValue: FloatingIndicatorDisplayInfo = {\r\n text,\r\n counter: previousValue_DisplayInfo_Green.current.counter + 1,\r\n };\r\n\r\n setDisplayInfo_Green(newValue);\r\n\r\n previousValue_DisplayInfo_Green.current = { ...newValue };\r\n },\r\n [setDisplayInfo_Green],\r\n );\r\n\r\n const hideFloatingLoadingIndicator_Green = useCallback((): void => {\r\n const newValue: FloatingIndicatorDisplayInfo = {\r\n text: previousValue_DisplayInfo_Green.current.text, // Keep the text the same when we hide things so it doesn't flicker in the UI\r\n counter: previousValue_DisplayInfo_Green.current.counter - 1,\r\n };\r\n\r\n setDisplayInfo_Green(newValue);\r\n\r\n previousValue_DisplayInfo_Green.current = { ...newValue };\r\n }, [setDisplayInfo_Green]);\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport { FloatingLoadingIndicatorContext, FloatingLoadingIndicatorContextProvider };\r\n","import React, { useCallback, useRef } from 'react';\r\nimport { Observable } from 'rxjs';\r\nimport { useObservableWithValue } from '../../../hooks/observables/useObservable';\r\n\r\ninterface LoadingPageOverlayContextInterface {\r\n loadingOverlayCounter$: Observable;\r\n showPageLoadingOverlay: () => void;\r\n hidePageLoadingOverlay: (forceHide?: boolean) => void;\r\n}\r\n\r\nconst LoadingPageOverlayContext = React.createContext(\r\n {} as LoadingPageOverlayContextInterface,\r\n);\r\n\r\nconst LoadingPageOverlayContextProvider: React.FC = (props) => {\r\n // NOTE: We maintain a counter of how many times this code was told to show the loading overlay\r\n // and use that to dictate when we display it.\r\n // We do this so code that uses this is responsible for cleaning up after itself by incrementing or decrementing\r\n // this counter via the methods to show or hide the loading overlay.\r\n const currCounterValue = useRef(0);\r\n\r\n const [loadingOverlayCounter$, setLoadingOverlayCounter] = useObservableWithValue();\r\n\r\n const showPageLoadingOverlay = useCallback((): void => {\r\n const newValue = currCounterValue.current + 1;\r\n\r\n currCounterValue.current = newValue;\r\n setLoadingOverlayCounter(newValue);\r\n }, [setLoadingOverlayCounter]);\r\n\r\n const hidePageLoadingOverlay = useCallback(\r\n (forceHide = false): void => {\r\n // If we want to force the loading overlay to hide, set the count to 0\r\n const newValue = forceHide ? 0 : Math.max(0, currCounterValue.current - 1);\r\n\r\n currCounterValue.current = newValue;\r\n setLoadingOverlayCounter(newValue);\r\n },\r\n [setLoadingOverlayCounter],\r\n );\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport { LoadingPageOverlayContext, LoadingPageOverlayContextProvider };\r\n","import { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { CommandBase } from '../../../classes/commands/CommandBase';\r\nimport GeneralConstants from '../../../constants/general';\r\nimport { CommandManagerService } from '../../../services/command/command-manager-service';\r\nimport { useLogger } from '../../../services/logger/Logger';\r\nimport { FloatingLoadingIndicatorContext } from '../../common-page-components/floating-loading-indicator/FloatingLoadingIndicatorContext';\r\nimport { BTGeneralContext } from '../../common-page-components/general-contexts/BTGeneralContext';\r\nimport { LoadingPageOverlayContext } from '../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport { NotificationPanelContext } from '../../common-page-components/notification-panel/NotificationPanelContext';\r\n\r\ninterface ReturnValue {\r\n executeCommand: (args: ExecuteCommandArgs) => Promise;\r\n\r\n executeCommandWithoutCallbacks: (\r\n commandToExecute: ICommand | (() => Promise) | null,\r\n ) => Promise;\r\n}\r\n\r\nconst useCommandServiceHelper = (): ReturnValue => {\r\n const { showErrorNotification } = useContext(NotificationPanelContext);\r\n\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n\r\n const { signalRResponseTimeout } = useContext(BTGeneralContext);\r\n\r\n const { showFloatingLoadingIndicator_Blue, hideFloatingLoadingIndicator_Blue } = useContext(\r\n FloatingLoadingIndicatorContext,\r\n );\r\n\r\n const { t } = useTranslation();\r\n\r\n const logger = useLogger();\r\n\r\n const executeCommand = useCallback(\r\n async ({\r\n commandToExecute,\r\n commandBeforeExecutionCallback,\r\n commandSuccessCallback,\r\n commandErrorCallback,\r\n commandExecutionType = 'floating-loading-overlay',\r\n customErrorMessage,\r\n commandTimeoutFunction,\r\n }: ExecuteCommandArgs): Promise => {\r\n if (!commandToExecute) {\r\n return false;\r\n }\r\n\r\n const executeCommandParameter = async () => {\r\n let success = false;\r\n\r\n try {\r\n if (commandBeforeExecutionCallback) {\r\n commandBeforeExecutionCallback();\r\n }\r\n\r\n let result: unknown | undefined = undefined;\r\n\r\n if (commandToExecute instanceof CommandBase) {\r\n result = await CommandManagerService.executeCommand(commandToExecute);\r\n } else {\r\n result = await (commandToExecute as () => Promise)();\r\n }\r\n\r\n if (commandSuccessCallback) {\r\n commandSuccessCallback(result);\r\n }\r\n\r\n success = true;\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), customErrorMessage || t('general:saveError'));\r\n\r\n // If something fails, turn off the loading overlay if we turned it on with\r\n // the intention of Signal R turning it off elsewhere.\r\n if (commandExecutionType === 'relies-on-signal-r-for-completion') {\r\n hidePageLoadingOverlay();\r\n }\r\n\r\n if (commandErrorCallback) {\r\n commandErrorCallback(error);\r\n }\r\n }\r\n\r\n return success;\r\n };\r\n\r\n let success = false;\r\n\r\n if (commandExecutionType === 'floating-loading-overlay') {\r\n showFloatingLoadingIndicator_Blue(t('general:saving'));\r\n\r\n success = await executeCommandParameter();\r\n\r\n hideFloatingLoadingIndicator_Blue();\r\n } else if (commandExecutionType === 'page-loading-overlay') {\r\n showPageLoadingOverlay();\r\n\r\n success = await executeCommandParameter();\r\n\r\n hidePageLoadingOverlay();\r\n } else if (commandExecutionType === 'relies-on-signal-r-for-completion') {\r\n showPageLoadingOverlay();\r\n\r\n success = await executeCommandParameter();\r\n\r\n if (signalRResponseTimeout.current) {\r\n clearTimeout(signalRResponseTimeout.current);\r\n }\r\n\r\n signalRResponseTimeout.current = setTimeout(() => {\r\n // If we never get a notification from SignalR in other code for whatever reason,\r\n // we need to get rid of the loading overlay after a long-enough delay\r\n if (commandTimeoutFunction) {\r\n commandTimeoutFunction();\r\n }\r\n\r\n hidePageLoadingOverlay(true);\r\n }, GeneralConstants.SIGNALR_WAIT_TIMEOUT);\r\n }\r\n\r\n return success;\r\n },\r\n [\r\n logger,\r\n showErrorNotification,\r\n t,\r\n hidePageLoadingOverlay,\r\n showFloatingLoadingIndicator_Blue,\r\n hideFloatingLoadingIndicator_Blue,\r\n showPageLoadingOverlay,\r\n signalRResponseTimeout,\r\n ],\r\n );\r\n\r\n const executeCommandWithoutCallbacks = useCallback(\r\n async (commandToExecute: ICommand | (() => Promise) | null): Promise => {\r\n return await executeCommand({\r\n commandToExecute: commandToExecute,\r\n commandExecutionType: 'floating-loading-overlay',\r\n });\r\n },\r\n [executeCommand],\r\n );\r\n\r\n return {\r\n executeCommand,\r\n executeCommandWithoutCallbacks,\r\n };\r\n};\r\n\r\ntype CommandExecutionTypes =\r\n | 'relies-on-signal-r-for-completion'\r\n | 'floating-loading-overlay'\r\n | 'page-loading-overlay';\r\n\r\ninterface ExecuteCommandArgs {\r\n commandToExecute: ICommand | (() => Promise) | null;\r\n commandExecutionType?: CommandExecutionTypes;\r\n showFullPageLoadingOverlay?: boolean;\r\n commandBeforeExecutionCallback?: () => void;\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n commandSuccessCallback?: (responseData?: any) => void;\r\n commandErrorCallback?: (error?: unknown) => void;\r\n // the function that will run if the timeout expires before we get a signalR notification that the command has completed.\r\n commandTimeoutFunction?: () => Promise;\r\n customErrorMessage?: string;\r\n}\r\n\r\nexport default useCommandServiceHelper;\r\n","import React, { useCallback } from 'react';\r\nimport { Observable } from 'rxjs';\r\nimport { useObservableWithValue } from '../../../hooks/observables/useObservable';\r\n\r\nexport interface ConfirmationOverlayDisplayInfo {\r\n currentConfirmationOverlayParameters: ConfirmationOverlayParameters | null;\r\n isDisplayed: boolean;\r\n hasBeenToggled: boolean;\r\n}\r\n\r\ninterface ConfirmationOverlayParameters {\r\n text: string;\r\n text2?: string;\r\n image?: 'bid-day-logo' | 'excel';\r\n allowEscapeKey?: boolean;\r\n buttons: ConfirmationOverlayButton[];\r\n}\r\n\r\ninterface ConfirmationOverlayButton {\r\n color?: 'normal' | 'gray';\r\n text: string;\r\n onClick: () => void;\r\n}\r\n\r\ninterface ConfirmationOverlayContextInterface {\r\n confirmationOverlaySet$: Observable;\r\n showConfirmationOverlay: (confirmationOverlayParameters: ConfirmationOverlayParameters) => void;\r\n hideConfirmationOverlay: () => void;\r\n}\r\n\r\nconst ConfirmationOverlayContext = React.createContext(\r\n {} as ConfirmationOverlayContextInterface,\r\n);\r\n\r\nconst ConfirmationOverlayContextProvider: React.FC = (props) => {\r\n const [confirmationOverlaySet$, setConfirmationOverlay] = useObservableWithValue<\r\n ConfirmationOverlayDisplayInfo\r\n >();\r\n\r\n const showConfirmationOverlay = useCallback(\r\n (confirmationOverlayParameters: ConfirmationOverlayParameters) => {\r\n setConfirmationOverlay({\r\n currentConfirmationOverlayParameters: confirmationOverlayParameters,\r\n isDisplayed: true,\r\n hasBeenToggled: true,\r\n });\r\n },\r\n [setConfirmationOverlay],\r\n );\r\n\r\n const hideConfirmationOverlay = useCallback(() => {\r\n setConfirmationOverlay({\r\n currentConfirmationOverlayParameters: null,\r\n isDisplayed: false,\r\n hasBeenToggled: true,\r\n });\r\n }, [setConfirmationOverlay]);\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport { ConfirmationOverlayContext, ConfirmationOverlayContextProvider };\r\n","import { useCallback, useContext } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { CommandHttpService } from '../../../services/command/command-http-service';\nimport { ConfirmationOverlayContext } from '../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport { LoadingPageOverlayContext } from '../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\nimport { NotificationPanelContext } from '../../common-page-components/notification-panel/NotificationPanelContext';\n\ninterface ReturnValue {\n showSampleDataDialog: () => void;\n}\n\nconst useSampleDataDialog = (): ReturnValue => {\n const { t } = useTranslation();\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n const { showErrorNotification, showSuccessNotification } = useContext(NotificationPanelContext);\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\n\n const showSampleDataDialog = useCallback(() => {\n showConfirmationOverlay({\n text: t('sample-data:dialogText'),\n buttons: [\n {\n text: t('general:yes'),\n onClick: async (): Promise => {\n try {\n showPageLoadingOverlay();\n hideConfirmationOverlay();\n\n const commandService = await CommandHttpService.getCommandHttpService();\n await commandService.post('sample-data');\n\n showSuccessNotification(t('general:success'), t('sample-data:dialogOnSuccess'));\n } catch {\n hideConfirmationOverlay();\n showErrorNotification(t('general:error'), t('sample-data:dialogOnError'));\n } finally {\n hidePageLoadingOverlay();\n }\n },\n color: 'normal',\n },\n {\n text: t('general:no'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n }, [\n hideConfirmationOverlay,\n hidePageLoadingOverlay,\n showConfirmationOverlay,\n showErrorNotification,\n showPageLoadingOverlay,\n showSuccessNotification,\n t,\n ]);\n\n return {\n showSampleDataDialog,\n };\n};\n\nexport default useSampleDataDialog;\n","// NOTE: When creating 'full' routes, we use an empty string as the first element in the array we are concatenating so we get a leading forward slash\r\nconst ErrorRoutes = {\r\n ERROR: ['', 'error'].join('/'),\r\n PAGENOTFOUND: ['', 'page-not-found'].join('/'),\r\n UNAUTHORIZED: ['', 'unauthorized'].join('/'),\r\n UNLICENSED: ['', 'unlicensed'].join('/'),\r\n};\r\n\r\nexport default ErrorRoutes;\r\n","const SETTINGS_ROOT = 'settings';\r\n\r\n// NOTE: When creating 'full' routes, we use an empty string as the first element in the array we are concatenating so we get a leading forward slash\r\nconst SettingsRoutes = {\r\n BASE: ['', SETTINGS_ROOT].join('/'),\r\n BIDPACKAGES: ['', SETTINGS_ROOT, 'bid-packages'].join('/'),\r\n FEES: ['', SETTINGS_ROOT, 'fees'].join('/'),\r\n GENERALCONDITIONS: ['', SETTINGS_ROOT, 'general-conditions'].join('/'),\r\n GENERALREQUIREMENTS: ['', SETTINGS_ROOT, 'general-requirements'].join('/'),\r\n USERPERMISSIONS: ['', SETTINGS_ROOT, 'user-permissions'].join('/'),\r\n UNITSOFMEASURE: ['', SETTINGS_ROOT, 'units-of-measure'].join('/'),\r\n PREFERENCES: ['', SETTINGS_ROOT, 'preferences'].join('/'),\r\n};\r\n\r\nexport default SettingsRoutes;\r\n","import ErrorRoutes from './error-routes';\r\nimport SettingsRoutes from './settings-routes';\r\n\r\nconst SITE_ROOT = '/';\r\nconst BID_PACKAGE = '/bid-package';\r\nconst BID_SUMMARY = '/bid-summary';\r\nconst HOME = '/home';\r\nconst PROJECT = '/project';\r\nconst PROJECTS = '/projects';\r\n\r\nconst ApplicationRoutes = {\r\n SITE_ROOT,\r\n HOME,\r\n BID_PACKAGE,\r\n BID_SUMMARY,\r\n PROJECT,\r\n PROJECTS,\r\n\r\n SETTINGS_BIDPACKAGES: SettingsRoutes.BIDPACKAGES,\r\n SETTINGS_FEES: SettingsRoutes.FEES,\r\n SETTINGS_GENERALCONDITIONS: SettingsRoutes.GENERALCONDITIONS,\r\n SETTINGS_GENERALREQUIREMENTS: SettingsRoutes.GENERALREQUIREMENTS,\r\n SETTINGS_USERPERMISSIONS: SettingsRoutes.USERPERMISSIONS,\r\n SETTINGS_UNITSOFMEASURE: SettingsRoutes.UNITSOFMEASURE,\r\n SETTINGS_PREFERENCES: SettingsRoutes.PREFERENCES,\r\n ERROR_ERROR: ErrorRoutes.ERROR,\r\n ERROR_PAGENOTFOUND: ErrorRoutes.PAGENOTFOUND,\r\n ERROR_UNAUTHORIZED: ErrorRoutes.UNAUTHORIZED,\r\n\r\n ERROR_UNLICENSED: ErrorRoutes.UNLICENSED,\r\n};\r\n\r\nexport default ApplicationRoutes;\r\n","import { IconName } from '@fortawesome/fontawesome-svg-core';\r\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport { sortBy } from 'lodash';\r\nimport moment from 'moment';\r\nimport React, { useContext, useEffect, useMemo, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Link } from 'react-router-dom';\r\nimport {\r\n Collapse,\r\n DropdownItem,\r\n DropdownMenu,\r\n DropdownToggle,\r\n Nav,\r\n Navbar,\r\n NavbarToggler,\r\n NavLink,\r\n UncontrolledDropdown,\r\n} from 'reactstrap';\r\nimport { Subscription } from 'rxjs';\r\nimport { UpdateCanLoadSampleDataCommand } from '../../../classes/commands/sample-data/update-can-load-sample-data';\r\nimport GeneralConstants from '../../../constants/general';\r\nimport AdminRoutes from '../../../constants/routes/admin-routes';\r\nimport { ProjectApi } from '../../../services';\r\nimport { AuthenticationService } from '../../../services/authentication/authentication-service';\r\nimport { isEnvironment } from '../../../utils/general';\r\nimport useCommandServiceHelper from '../../shared-page-components/hooks/useCommandServiceHelper';\r\nimport useSampleDataDialog from '../../shared-page-components/hooks/useSampleDataDialog';\r\nimport { BTGeneralContext } from '../general-contexts/BTGeneralContext';\r\nimport ApplicationRoutes from './../../../constants/routes';\r\nimport './NavigationMenu.scss';\r\n\r\ninterface CustomNavigationLink {\r\n title: string;\r\n url?: string;\r\n icon?: IconName;\r\n hasDivider_Bottom?: boolean;\r\n hasDivider_Top?: boolean;\r\n sortOrder?: number;\r\n grayBackground?: boolean;\r\n onClick?: () => void;\r\n subLinks?: CustomNavigationLink[];\r\n dataTestId?: string;\r\n}\r\n\r\nconst NavigationMenu: React.FC = () => {\r\n const { t } = useTranslation();\r\n const { showSampleDataDialog } = useSampleDataDialog();\r\n const { pageScroll_Y$, systemSettings, setSystemSettings } = useContext(BTGeneralContext);\r\n const canLoadSampleData = useMemo(() => systemSettings?.canLoadSampleData ?? false, [\r\n systemSettings,\r\n ]);\r\n\r\n const [pageIsScrolled_Y, setPageIsScrolled_Y] = useState(false);\r\n\r\n const [mobileNavigationMenuIsOpen, setMobileNavigationMenuIsOpen] = useState(false);\r\n const [navigationLinks, setNavigationLinks] = useState([]);\r\n const [loadingProgressBarIsVisible, setLoadingProgressBarIsVisible] = useState();\r\n const userInformation = AuthenticationService.currentUserInfo;\r\n const { executeCommandWithoutCallbacks } = useCommandServiceHelper();\r\n\r\n const shouldShowHolidayEasterEgg = (type: 'thanksgiving' | 'winter'): boolean => {\r\n // Only show this for logged in users, outside of production\r\n if (!userInformation || isEnvironment('prod')) {\r\n return false;\r\n }\r\n\r\n const today = moment().startOf('day');\r\n\r\n switch (type) {\r\n case 'thanksgiving':\r\n return today.month() === 10 && today.date() >= 10 && today.date() <= 30;\r\n\r\n case 'winter':\r\n return today.month() === 11 && today.date() >= 1 && today.date() <= 31;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n // Listen for events\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n pageScroll_Y$.subscribe((offset) => {\r\n setPageIsScrolled_Y(offset >= 25);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [pageScroll_Y$]);\r\n\r\n useEffect(() => {\r\n // Toggle the visibility of the loading progress bar when this component loads\r\n setLoadingProgressBarIsVisible(true);\r\n\r\n const timer = setTimeout(() => {\r\n setLoadingProgressBarIsVisible(false);\r\n }, 1000);\r\n\r\n return () => clearTimeout(timer);\r\n }, []);\r\n\r\n const toggleMobileNavigationLinks = (): void => {\r\n setMobileNavigationMenuIsOpen(!mobileNavigationMenuIsOpen);\r\n };\r\n\r\n useEffect(() => {\r\n const generateAndSetNavigationLinks = async (): Promise => {\r\n const newNavigationLinks: CustomNavigationLink[] = [\r\n { title: 'Home', url: ApplicationRoutes.SITE_ROOT },\r\n ];\r\n\r\n if (userInformation) {\r\n if (userInformation.isLicensed) {\r\n // Settings links\r\n const settingsNavigationLink: CustomNavigationLink = { title: 'Settings', subLinks: [] };\r\n\r\n if (\r\n userInformation.userIsAdmin() ||\r\n userInformation.userIsProjectAdmin() ||\r\n userInformation.userIsBidDaySupport()\r\n ) {\r\n settingsNavigationLink.subLinks!.push({\r\n title: t('navigation:userPermissions'),\r\n url: ApplicationRoutes.SETTINGS_USERPERMISSIONS,\r\n sortOrder: 7,\r\n });\r\n }\r\n\r\n if (userInformation.userIsAdmin() || userInformation.userIsBidDaySupport()) {\r\n settingsNavigationLink.subLinks!.push(\r\n {\r\n title: t('navigation:bidPackages'),\r\n url: ApplicationRoutes.SETTINGS_BIDPACKAGES,\r\n sortOrder: 1,\r\n },\r\n {\r\n title: t('navigation:fees'),\r\n url: ApplicationRoutes.SETTINGS_FEES,\r\n sortOrder: 2,\r\n },\r\n {\r\n title: t('general-conditions:generalConditions'),\r\n url: ApplicationRoutes.SETTINGS_GENERALCONDITIONS,\r\n sortOrder: 3,\r\n },\r\n {\r\n title: t('navigation:generalRequirements'),\r\n url: ApplicationRoutes.SETTINGS_GENERALREQUIREMENTS,\r\n sortOrder: 4,\r\n },\r\n {\r\n title: t('navigation:preferences'),\r\n url: ApplicationRoutes.SETTINGS_PREFERENCES,\r\n sortOrder: 5,\r\n },\r\n {\r\n title: t('units-of-measure:unitsOfMeasure'),\r\n url: ApplicationRoutes.SETTINGS_UNITSOFMEASURE,\r\n sortOrder: 6,\r\n },\r\n );\r\n\r\n // Sample data\r\n if (canLoadSampleData && userInformation.userIsAdmin()) {\r\n // If sample data can be loaded and NO PROJECTS ADDED,\r\n // show the navigation link\r\n const thereAreNoProjects = (await ProjectApi.getProjectCount()) === 0;\r\n if (thereAreNoProjects) {\r\n settingsNavigationLink.subLinks!.push({\r\n icon: 'database',\r\n title: t('sample-data:navigationMenuOption'),\r\n onClick: showSampleDataDialog,\r\n hasDivider_Top: true,\r\n grayBackground: true,\r\n sortOrder: 8,\r\n });\r\n } else {\r\n // If sample data can be loaded but PROJECTS HAVE BEEN ADDED,\r\n // set CanLoadSampleData = False\r\n await executeCommandWithoutCallbacks(new UpdateCanLoadSampleDataCommand(false));\r\n setSystemSettings((currentValue) => ({\r\n ...currentValue,\r\n canLoadSampleData: false,\r\n generalConditionsCode: currentValue?.generalConditionsCode ?? null,\r\n }));\r\n }\r\n }\r\n }\r\n\r\n if (settingsNavigationLink.subLinks!.length > 0) {\r\n settingsNavigationLink.subLinks = sortBy(\r\n settingsNavigationLink.subLinks!,\r\n (v) => v.sortOrder ?? 100,\r\n );\r\n\r\n newNavigationLinks.push(settingsNavigationLink);\r\n }\r\n\r\n // Tools links\r\n const toolsNavigationLink: CustomNavigationLink = {\r\n title: 'Internal',\r\n subLinks: [],\r\n };\r\n\r\n if ((toolsNavigationLink?.subLinks?.length || 0) > 0) {\r\n newNavigationLinks.push(toolsNavigationLink);\r\n }\r\n }\r\n\r\n if (userInformation.userIsAdmin() || userInformation.userIsBidDaySupport()) {\r\n newNavigationLinks.push({\r\n title: t('general:admin'),\r\n subLinks: [\r\n {\r\n title: t('navigation:frozenEntities'),\r\n url: AdminRoutes.FROZEN_ENTITIES,\r\n },\r\n ],\r\n });\r\n }\r\n\r\n newNavigationLinks.push({\r\n title: userInformation.name,\r\n subLinks: [\r\n {\r\n title: t('general:logOut'),\r\n onClick: (): void => {\r\n AuthenticationService.logout();\r\n },\r\n },\r\n ],\r\n dataTestId: 'user-test-id',\r\n });\r\n } else {\r\n newNavigationLinks.push({\r\n title: t('general:signIn'),\r\n onClick: (): void => {\r\n AuthenticationService.signIn();\r\n },\r\n });\r\n }\r\n\r\n setNavigationLinks(newNavigationLinks);\r\n };\r\n\r\n generateAndSetNavigationLinks();\r\n }, [\r\n canLoadSampleData,\r\n executeCommandWithoutCallbacks,\r\n setSystemSettings,\r\n showSampleDataDialog,\r\n t,\r\n userInformation,\r\n ]);\r\n\r\n return (\r\n \r\n
\r\n
\r\n \r\n \"Bid\r\n\r\n

{GeneralConstants.PRODUCT_NAME_FULL}

\r\n\r\n {shouldShowHolidayEasterEgg('thanksgiving') ? (\r\n {\r\n const themeClassName = 'fall-theme';\r\n\r\n if (document.body.classList.contains(themeClassName)) {\r\n document.body.classList.remove(themeClassName);\r\n } else {\r\n document.body.classList.add(themeClassName);\r\n }\r\n\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }}\r\n />\r\n ) : (\r\n <>\r\n )}\r\n\r\n {shouldShowHolidayEasterEgg('winter') ? (\r\n {\r\n const themeClassName = 'winter-theme';\r\n\r\n if (document.body.classList.contains(themeClassName)) {\r\n document.body.classList.remove(themeClassName);\r\n } else {\r\n document.body.classList.add(themeClassName);\r\n }\r\n\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }}\r\n />\r\n ) : (\r\n <>\r\n )}\r\n \r\n
\r\n\r\n
\r\n {navigationLinks.map((currLink) => {\r\n // If the current link has a URL, show it as a regular link.\r\n // If the current link has an array of sublinks, show the current link and sublinks as a dropdown.\r\n // NOTE: This code only handles one level of sublinks for the time being.\r\n if (currLink.url || currLink.onClick) {\r\n return (\r\n
\r\n {\r\n if (currLink.onClick) {\r\n currLink.onClick();\r\n\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }\r\n }}\r\n >\r\n {currLink.icon ? (\r\n
\r\n {currLink.title}\r\n\r\n \r\n \r\n \r\n
\r\n ) : (\r\n {currLink.title}\r\n )}\r\n \r\n
\r\n );\r\n } else if (currLink.subLinks && currLink.subLinks.length) {\r\n return (\r\n \r\n \r\n \r\n {currLink.icon ? (\r\n
\r\n {currLink.title}\r\n\r\n \r\n \r\n \r\n
\r\n ) : (\r\n \r\n {currLink.title}\r\n \r\n )}\r\n
\r\n\r\n \r\n {currLink.subLinks.map((currSubLink) => {\r\n return (\r\n
\r\n {currSubLink.hasDivider_Top ? : <>}\r\n\r\n \r\n {\r\n if (currSubLink.onClick) {\r\n currSubLink.onClick();\r\n\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }\r\n }}\r\n >\r\n {currSubLink.icon ? (\r\n
\r\n {currSubLink.title}\r\n\r\n \r\n \r\n \r\n
\r\n ) : (\r\n {currSubLink.title}\r\n )}\r\n \r\n
\r\n\r\n {currSubLink.hasDivider_Bottom ? : <>}\r\n
\r\n );\r\n })}\r\n
\r\n
\r\n
\r\n );\r\n }\r\n\r\n throw new Error('navigationLinks was not in an expectedFormat');\r\n })}\r\n
\r\n\r\n
\r\n \r\n
\r\n \r\n\r\n \r\n \r\n \r\n\r\n {loadingProgressBarIsVisible ? (\r\n
\r\n
\r\n
\r\n ) : (\r\n <>\r\n )}\r\n \r\n );\r\n};\r\n\r\nexport default NavigationMenu;\r\n","import React from 'react';\r\nimport NavigationMenu from './../navigation-menu/NavigationMenu';\r\nimport './Layout.scss';\r\n\r\nconst Layout: React.FC = (props) => {\r\n return (\r\n
\r\n \r\n\r\n
\r\n {props.children}\r\n\r\n {/* NOTE: We add a bottom spacer so the user doesn't have to deal with content\r\n being at the very bottom of a page */}\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default Layout;\r\n","import React, { useEffect, useState } from 'react';\r\nimport { Route, RouteProps, useHistory } from 'react-router';\r\nimport ApplicationRoutes from '../../../constants/routes';\r\nimport { AuthenticationService } from '../../../services/authentication/authentication-service';\r\n\r\ninterface Props {\r\n requiredUserRoles?: string[];\r\n allowAnyRoles?: boolean; // Specifies that a user having any of the required roles is OK (as opposed to requiring every role)\r\n}\r\n\r\nconst AuthenticatedRoute: React.FC = (props) => {\r\n const [shouldRender, setShouldRender] = useState(false);\r\n const history = useHistory();\r\n const userInfo = AuthenticationService.currentUserInfo;\r\n\r\n useEffect(() => {\r\n const redirectUser = (): void => {\r\n // Explicitly replace the current URL\r\n history.replace(ApplicationRoutes.ERROR_UNAUTHORIZED);\r\n };\r\n\r\n if (userInfo === null) {\r\n redirectUser();\r\n return;\r\n }\r\n\r\n // Check authorization if it's required\r\n if (props.requiredUserRoles) {\r\n const allUserRoles = userInfo.roles.map((v) => v.id);\r\n\r\n if (\r\n (props.allowAnyRoles &&\r\n !props.requiredUserRoles.some((v) => allUserRoles.some((m) => m === v))) ||\r\n (!props.allowAnyRoles &&\r\n !props.requiredUserRoles.every((v) => allUserRoles.some((m) => m === v)))\r\n ) {\r\n redirectUser();\r\n return;\r\n }\r\n }\r\n\r\n setShouldRender(true);\r\n }, [props.requiredUserRoles, props.allowAnyRoles, history, userInfo]);\r\n\r\n if (shouldRender) {\r\n return (\r\n
\r\n \r\n
\r\n );\r\n } else {\r\n return <>;\r\n }\r\n};\r\n\r\nexport default AuthenticatedRoute;\r\n","import React, { useEffect, useState } from 'react';\r\nimport { RouteProps, useHistory, useRouteMatch } from 'react-router';\r\nimport ApplicationRoutes from '../../../../constants/routes';\r\nimport { ProjectApi } from '../../../../services';\r\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\r\nimport { isValidUuid } from '../../../../utils/uuid';\r\n\r\nconst ProjectGuard: React.FC = (props) => {\r\n const history = useHistory();\r\n const userInfo = AuthenticationService.currentUserInfo;\r\n const [shouldRender, setShouldRender] = useState(false);\r\n\r\n const projectId =\r\n useRouteMatch(`${ApplicationRoutes.PROJECT}/:projectId?`)?.params\r\n .projectId || null;\r\n\r\n useEffect(() => {\r\n const checkUserPermission = async () => {\r\n const redirectToError = (): void => {\r\n // Explicitly replace the current URL when an invalid uuid is provided\r\n history.replace(ApplicationRoutes.ERROR_ERROR);\r\n };\r\n const redirectToUnauthorized = (): void => {\r\n // Explicitly replace the current URL when an unauthorized user attempts navigation\r\n history.replace(ApplicationRoutes.ERROR_UNAUTHORIZED);\r\n };\r\n\r\n if (userInfo === null) {\r\n redirectToUnauthorized();\r\n return;\r\n }\r\n\r\n // If a projectId parameter was supplied, the user is trying to access the edit version of the page\r\n if (projectId && isValidUuid(projectId)) {\r\n // If the projectId is not a valid uuid, redirect\r\n if (!isValidUuid(projectId)) {\r\n redirectToError();\r\n return;\r\n }\r\n // If the project is valid, but the project is closed or the user is not one of the projectAdmins, redirect\r\n const project = await ProjectApi.getProjectInfoById(projectId);\r\n if (project && (project.isClosed || !project.projectAdmins?.includes(userInfo.email))) {\r\n redirectToUnauthorized();\r\n return;\r\n }\r\n }\r\n\r\n // If the previous checks have passed, render the children to the child component\r\n setShouldRender(true);\r\n };\r\n\r\n checkUserPermission();\r\n }, [projectId, props.location, history, userInfo]);\r\n\r\n if (shouldRender) {\r\n return <>{props.children};\r\n } else {\r\n return <>;\r\n }\r\n};\r\nexport default ProjectGuard;\r\n","import React, { useCallback } from 'react';\nimport { Observable } from 'rxjs';\nimport { useObservableWithValue } from '../../../hooks/observables/useObservable';\nimport { BTDropDownListOption } from '../inputs/BTDropDownList';\n\nexport interface SupportOverlayDisplayInfo {\n currentSupportOverlayParameters: SupportOverlayParameters | null;\n isDisplayed: boolean;\n hasBeenToggled: boolean;\n}\n\ninterface SupportOverlayParameters {\n text: string;\n options: BTDropDownListOption[];\n onCancelClick: () => void;\n onClientSelected: (clientOrgId: string) => void;\n}\n\ninterface SupportOverlayContextInterface {\n supportOverlaySet$: Observable;\n showSupportOverlay: (supportOverlayParameters: SupportOverlayParameters) => void;\n hideSupportOverlay: () => void;\n}\n\nconst SupportOverlayContext = React.createContext(\n {} as SupportOverlayContextInterface,\n);\n\nconst SupportOverlayContextProvider: React.FC = (props) => {\n const [supportOverlaySet$, setSupportOverlay] = useObservableWithValue<\n SupportOverlayDisplayInfo\n >();\n\n const showSupportOverlay = useCallback(\n (supportOverlayParameters: SupportOverlayParameters) => {\n setSupportOverlay({\n currentSupportOverlayParameters: supportOverlayParameters,\n isDisplayed: true,\n hasBeenToggled: true,\n });\n },\n [setSupportOverlay],\n );\n\n const hideSupportOverlay = useCallback(() => {\n setSupportOverlay({\n currentSupportOverlayParameters: null,\n isDisplayed: false,\n hasBeenToggled: true,\n });\n }, [setSupportOverlay]);\n\n return (\n \n {props.children}\n \n );\n};\n\nexport { SupportOverlayContext, SupportOverlayContextProvider };\n","import { IconProp } from '@fortawesome/fontawesome-svg-core';\r\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { ForwardRefRenderFunction } from 'react';\r\nimport { Button } from 'reactstrap';\r\nimport './BTButton.scss';\r\n\r\ninterface Props {\r\n color?: 'normal' | 'gray';\r\n type?: 'submit' | 'button';\r\n align?: 'left' | 'center' | 'right';\r\n roundedCorners?: boolean;\r\n text: string;\r\n icon?: IconProp;\r\n disabled?: boolean;\r\n onClick?: () => void;\r\n tooltip?: string;\r\n tabIndex?: number;\r\n ref?: React.Ref;\r\n dataAttributes?: Record; // A collection of \"data\" attributes that will be outputted on the cell (ex. data-column-name=\"xxx\")\r\n}\r\n\r\nconst BTButton: ForwardRefRenderFunction = (props, ref) => {\r\n let buttonStyleCssClass = '';\r\n\r\n switch (props.color) {\r\n case 'gray':\r\n buttonStyleCssClass = 'grayButton';\r\n break;\r\n default:\r\n break;\r\n }\r\n\r\n if (props.roundedCorners) {\r\n buttonStyleCssClass += ' roundedCorners';\r\n }\r\n\r\n const getStyles = (): Dictionary => {\r\n const returnValue: Dictionary = {};\r\n\r\n if (props.align) {\r\n returnValue.textAlign = props.align;\r\n }\r\n\r\n return returnValue;\r\n };\r\n\r\n return (\r\n {\r\n if (!props.disabled && props.onClick) {\r\n props.onClick();\r\n }\r\n }}\r\n disabled={props.disabled}\r\n title={props.tooltip}\r\n type={props.type || 'button'}\r\n tabIndex={props.tabIndex}\r\n style={getStyles()}\r\n {...props.dataAttributes}\r\n >\r\n {props.icon ? : <>}\r\n\r\n {props.text}\r\n \r\n );\r\n};\r\n\r\nexport default React.forwardRef(BTButton);\r\n","import React from 'react';\r\nimport './PageHeader.scss';\r\n\r\n// A component we can use to make sure all page headers are formatted the same way.\r\n// This is useful for other code that runs selectors against this app (QA / WalkMe).\r\nconst PageHeader: React.FC<{ text: string }> = ({ text }) => {\r\n return (\r\n

\r\n \r\n {text}\r\n \r\n

\r\n );\r\n};\r\n\r\nexport default PageHeader;\r\n","import React from 'react';\r\nimport error from './../../assets/icons/error.svg';\r\nimport exclamation from './../../assets/icons/exclamation.svg';\r\nimport stop from './../../assets/icons/stop.svg';\r\nimport snowflake from './../../assets/icons/snowflake.svg';\r\nimport './SvgImage.scss';\r\n\r\nexport type SvgImages = 'error' | 'exclamation' | 'stop' | 'snowflake';\r\n\r\ntype SvgImageSizes = 'sm' | 'md' | 'lg' | 'xl';\r\n\r\ninterface Props {\r\n image: SvgImages;\r\n size?: SvgImageSizes;\r\n}\r\n\r\nconst SvgImage: React.FC = ({ image, size }) => {\r\n const getSvgImage = (): string => {\r\n switch (image) {\r\n case 'error':\r\n return error;\r\n\r\n case 'exclamation':\r\n return exclamation;\r\n\r\n case 'stop':\r\n return stop;\r\n\r\n case 'snowflake':\r\n return snowflake;\r\n\r\n default:\r\n return '';\r\n }\r\n };\r\n\r\n const getSizeClass = (): string => {\r\n switch (size) {\r\n case 'sm':\r\n return 'sm';\r\n\r\n case 'md':\r\n return 'md';\r\n\r\n case 'xl':\r\n return 'xl';\r\n\r\n case 'lg':\r\n default:\r\n return 'lg';\r\n }\r\n };\r\n\r\n return (\r\n
\r\n {image}\r\n
\r\n );\r\n};\r\n\r\nexport default SvgImage;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { groupBy, orderBy, sortBy } from 'lodash';\nimport moment from 'moment';\nimport React, { useContext, useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory } from 'react-router';\nimport ApplicationRoutes from '../../../../constants/routes';\nimport { FrozenEntitiesApi } from '../../../../services';\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\nimport { Logger, useLogger } from '../../../../services/logger/Logger';\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport BTButton from '../../../common-page-components/controls/button/BTButton';\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\nimport SvgImage from '../../../common-page-components/svg-image/SvgImage';\nimport './FrozenEntitiesAdminPage.scss';\n\ninterface FrozenEntityEditableListing extends FrozenEntityListing {\n syncStatus: FrozenEntityStatus | null;\n unfreezeStatus: FrozenEntityStatus | null;\n}\n\ntype FrozenEntityStatus =\n | 'attempting-resync'\n | 'attempting-unfreeze'\n | 'resync-failed'\n | 'resync-succeeded'\n | 'unfreeze-failed'\n | 'unfreeze-succeeded';\n\nconst FrozenEntitiesAdminPage: React.FC = () => {\n const { t } = useTranslation();\n\n const logger = useLogger();\n const history = useHistory();\n\n const pageDataIsLoading = useRef(false);\n\n const { hidePageLoadingOverlay, showPageLoadingOverlay } = useContext(LoadingPageOverlayContext);\n\n const { showErrorNotification } = useContext(NotificationPanelContext);\n\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n\n const [groupedFrozenEntitiesData, setGroupedFrozenEntitiesData] = useState<\n Record\n >({});\n\n const userIsBidDaySupport = AuthenticationService.currentUserInfo?.userIsBidDaySupport();\n\n useEffect(() => {\n const loadPageData = async () => {\n if (pageDataIsLoading.current) {\n return;\n }\n\n pageDataIsLoading.current = true;\n\n try {\n showPageLoadingOverlay();\n\n const frozenEntitiesListings = await FrozenEntitiesApi.getFrozenEntitiesListings();\n const frozenEntitiesEditableListings: FrozenEntityEditableListing[] = frozenEntitiesListings.map(\n (v) => {\n return {\n dateFrozen: v.dateFrozen!,\n entityId: v.entityId!,\n entityType: v.entityType! as FrozenEntityTypes,\n name: v.name,\n metadata1: v.metadata1,\n metadata2: v.metadata2,\n syncStatus: null,\n unfreezeStatus: null,\n };\n },\n );\n\n setGroupedFrozenEntitiesData(groupFrozenEntitiesData(frozenEntitiesEditableListings));\n } catch {\n showErrorNotification(t('general:error'), t('general:error_Generic'));\n } finally {\n hidePageLoadingOverlay();\n }\n };\n\n loadPageData();\n }, [hidePageLoadingOverlay, showErrorNotification, showPageLoadingOverlay, t]);\n\n const onFrozenEntityNameClick = (frozenEntityType: FrozenEntityTypes, entityId: string): void => {\n switch (frozenEntityType as FrozenEntityTypes) {\n case 'BidPackage':\n history.push(`${ApplicationRoutes.BID_PACKAGE}/${entityId}`);\n break;\n\n case 'Project':\n history.push(`${ApplicationRoutes.BID_SUMMARY}/${entityId}`);\n break;\n }\n };\n\n const retrySync = (\n frozenEntityType: FrozenEntityTypes,\n entityId: string,\n entityName: string,\n ): void => {\n showConfirmationOverlay({\n text: t('frozen-entities:retrySyncConfirmation', {\n entityName,\n }),\n buttons: [\n {\n text: t('frozen-entities:retrySync'),\n onClick: async (): Promise => {\n hideConfirmationOverlay();\n\n const itemToUpdate = groupedFrozenEntitiesData[frozenEntityType]?.find(\n (v) => v.entityId === entityId,\n );\n\n // Only do something if the status is empty or is in an error state\n if (!itemToUpdate?.syncStatus || itemToUpdate.syncStatus === 'resync-failed') {\n updateFrozenEntityState(frozenEntityType, entityId, 'attempting-resync', undefined);\n\n let newStatus: FrozenEntityStatus | null = null;\n\n try {\n await FrozenEntitiesApi.syncEntity(entityId);\n\n newStatus = 'resync-succeeded';\n } catch {\n newStatus = 'resync-failed';\n }\n\n updateFrozenEntityState(frozenEntityType, entityId, newStatus, undefined);\n }\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n };\n\n const unfreezeEntity = (\n frozenEntityType: FrozenEntityTypes,\n entityId: string,\n entityName: string,\n ): void => {\n showConfirmationOverlay({\n text: t('frozen-entities:unfreezeConfirmation', {\n entityName,\n }),\n buttons: [\n {\n text: t('frozen-entities:unfreeze'),\n onClick: async (): Promise => {\n hideConfirmationOverlay();\n\n const itemToUpdate = groupedFrozenEntitiesData[frozenEntityType]?.find(\n (v) => v.entityId === entityId,\n );\n\n // Only do something if the status is empty or is in an error state\n if (\n !itemToUpdate?.unfreezeStatus ||\n itemToUpdate.unfreezeStatus === 'unfreeze-failed'\n ) {\n updateFrozenEntityState(frozenEntityType, entityId, undefined, 'attempting-unfreeze');\n\n let newStatus: FrozenEntityStatus | null = null;\n\n try {\n await FrozenEntitiesApi.unfreezeEntity(entityId, frozenEntityType);\n\n newStatus = 'unfreeze-succeeded';\n } catch {\n newStatus = 'unfreeze-failed';\n }\n\n updateFrozenEntityState(frozenEntityType, entityId, undefined, newStatus);\n }\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n };\n\n const updateFrozenEntityState = (\n frozenEntityType: string,\n entityId: string,\n newSyncStatus: FrozenEntityStatus | undefined,\n newUnfreezeStatus: FrozenEntityStatus | undefined,\n ): void => {\n setGroupedFrozenEntitiesData((currValue) => {\n const indexToUpdate = currValue[frozenEntityType as string]?.findIndex(\n (v) => v.entityId === entityId,\n );\n\n if (indexToUpdate !== undefined && indexToUpdate > -1) {\n const copy = { ...currValue };\n const copy2 = [...copy[frozenEntityType as string]];\n\n copy2[indexToUpdate] = {\n ...copy[frozenEntityType as string][indexToUpdate],\n unfreezeStatus:\n newUnfreezeStatus ?? copy[frozenEntityType as string][indexToUpdate].unfreezeStatus,\n syncStatus: newSyncStatus ?? copy[frozenEntityType as string][indexToUpdate].syncStatus,\n };\n\n copy[frozenEntityType as string] = copy2;\n return copy;\n }\n\n return currValue;\n });\n };\n\n return (\n
\n
\n
\n \n\n \n
\n
\n\n
\n {!Object.keys(groupedFrozenEntitiesData).length ? (\n

{t('frozen-entities:noFrozenEntitiesMessage')}

\n ) : (\n <>\n )}\n\n {Object.keys(groupedFrozenEntitiesData).map((currKey) => {\n return (\n
\n

{getDisplayTextForEntityType(logger, t, currKey)}

\n\n {groupedFrozenEntitiesData[currKey].map((currEntity) => {\n return (\n \n
\n
\n
\n
\n
\n \n \n
\n\n
\n \n \n
\n
\n\n {currEntity.metadata2 ? (\n
\n {Object.keys(currEntity.metadata2)[0] ? (\n \n ) : (\n <>\n )}\n\n \n
\n ) : (\n <>\n )}\n\n {currEntity.metadata1 ? (\n
\n {Object.keys(currEntity.metadata1)[0] ? (\n \n ) : (\n <>\n )}\n\n \n
\n ) : (\n <>\n )}\n\n
\n
\n {Object.keys(currEntity.name)[0] ? (\n \n ) : (\n <>\n )}\n\n {\n if (isFrozenEntityNameClickable(currEntity.entityType)) {\n onFrozenEntityNameClick(\n currEntity.entityType,\n currEntity.entityId,\n );\n }\n }}\n >\n {currEntity.name[Object.keys(currEntity.name)[0]]}\n \n
\n
\n
\n
\n\n
\n
\n
\n {currEntity.syncStatus === 'attempting-resync' ? (\n \n ) : (\n <>\n )}\n\n {currEntity.syncStatus === 'resync-failed' ? (\n \n ) : (\n <>\n )}\n\n {currEntity.syncStatus === 'resync-succeeded' ? (\n \n ) : (\n <>\n )}\n
\n\n
\n\n {\n retrySync(\n currKey as FrozenEntityTypes,\n currEntity.entityId,\n currEntity.name[Object.keys(currEntity.name)[0]],\n );\n }}\n disabled={\n currEntity.syncStatus === 'attempting-resync' ||\n currEntity.syncStatus === 'resync-succeeded' ||\n currEntity.unfreezeStatus === 'attempting-unfreeze' ||\n currEntity.unfreezeStatus === 'unfreeze-succeeded'\n }\n />\n
\n\n
\n
\n {currEntity.unfreezeStatus === 'attempting-unfreeze' ? (\n \n ) : (\n <>\n )}\n\n {currEntity.unfreezeStatus === 'unfreeze-failed' ? (\n \n ) : (\n <>\n )}\n\n {currEntity.unfreezeStatus === 'unfreeze-succeeded' ? (\n \n ) : (\n <>\n )}\n
\n\n
\n\n {\n unfreezeEntity(\n currKey as FrozenEntityTypes,\n currEntity.entityId,\n currEntity.name[Object.keys(currEntity.name)[0]],\n );\n }}\n disabled={\n !userIsBidDaySupport ||\n currEntity.unfreezeStatus === 'attempting-unfreeze' ||\n currEntity.unfreezeStatus === 'unfreeze-succeeded' ||\n currEntity.syncStatus === 'attempting-resync' ||\n currEntity.syncStatus === 'resync-succeeded'\n }\n />\n
\n
\n
\n
\n );\n })}\n
\n );\n })}\n
\n
\n );\n};\n\nconst groupFrozenEntitiesData = (\n frozenEntitiesListing: FrozenEntityEditableListing[],\n): Record => {\n const returnValue: Record = {};\n\n const groupedItems = groupBy(frozenEntitiesListing, (v) => v.entityType);\n\n sortBy(Object.keys(groupedItems), (v) => v).forEach((v) => {\n returnValue[v] = orderBy(\n groupedItems[v],\n [\n (m) => (m.metadata2 ? m.metadata2[Object.keys(m.metadata2)[0]] : 1),\n (m) => (m.metadata1 ? m.metadata1[Object.keys(m.metadata1)[0]] : 1),\n (m) => m.name,\n ],\n ['asc', 'asc', 'asc'],\n );\n });\n\n return returnValue;\n};\n\nconst getDisplayTextForEntityType = (\n logger: Logger,\n t: (input: string) => string,\n entityType: string,\n) => {\n switch (entityType as FrozenEntityTypes) {\n case 'AdjustmentNotes':\n return t('bid-package:adjustmentNotes');\n\n case 'BidDayApplication':\n return t('general:bidDayApplication');\n\n case 'BidDaySystemSettings':\n return t('general:bidDaySystemSettings');\n\n case 'BidderFileUploadContainer':\n return t('general:bidderFileUploadContainer');\n\n case 'BidderNotes':\n return t('bid-package:bidderNotes');\n\n case 'BidPackage':\n return t('general:bidPackages');\n\n case 'BidPackageNotes':\n return t('bid-package:bidPackageNotes');\n\n case 'Project':\n return t('general:projects');\n\n case 'ProjectNotes':\n return t('general:projectNotes');\n\n case 'ProjectFileUploadContainer':\n return t('general:projectFileUploadContainer');\n\n default:\n logger.logWarning(`No display text found for entity type \"${entityType}\"`);\n }\n};\n\nconst isFrozenEntityNameClickable = (entityType: FrozenEntityTypes): boolean => {\n const clickableEntityTypes: FrozenEntityTypes[] = ['BidPackage', 'Project'];\n return clickableEntityTypes.includes(entityType);\n};\n\nexport default FrozenEntitiesAdminPage;\n","import React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router';\r\nimport ApplicationRoutes from '../../../../../constants/routes';\r\nimport { isEnvironment } from '../../../../../utils/general';\r\nimport SvgImage from '../../../../common-page-components/svg-image/SvgImage';\r\n\r\nconst GenericErrorPage: React.FC = () => {\r\n const history = useHistory();\r\n const { t } = useTranslation();\r\n\r\n return (\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n\r\n
\r\n

{t('errors:errorMessage_Generic')}

\r\n
\r\n\r\n {isEnvironment('local') ? (\r\n
\r\n history.push(ApplicationRoutes.SITE_ROOT)}\r\n title={t('errors:clickHereToGoHome')}\r\n />\r\n
\r\n ) : (\r\n <>\r\n )}\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default GenericErrorPage;\r\n","import React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport SvgImage from '../../../../common-page-components/svg-image/SvgImage';\r\n\r\nconst PageNotFoundPage: React.FC = () => {\r\n const { t } = useTranslation();\r\n\r\n return (\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n\r\n
\r\n

{t('errors:errorMessage_PageNotFound')}

\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default PageNotFoundPage;\r\n","import React, { useContext, useEffect, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router';\r\nimport ApplicationRoutes from '../../../../../constants/routes';\r\nimport { isEnvironment } from '../../../../../utils/general';\r\nimport { LoadingPageOverlayContext } from '../../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport SvgImage from '../../../../common-page-components/svg-image/SvgImage';\r\n\r\nconst UnauthorizedPage: React.FC = () => {\r\n const { t } = useTranslation();\r\n const history = useHistory();\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n\r\n const [pageIsDisplayed, setPageIsDisplayed] = useState(false);\r\n\r\n useEffect(() => {\r\n // If the user is logged in, we want to redirect them to the home page\r\n const checkUserAuthenticationStatus = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n // Display the page as usual if the user is not logged in\r\n setPageIsDisplayed(true);\r\n } catch {\r\n // Display the page as usual if an error occurred\r\n setPageIsDisplayed(true);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n checkUserAuthenticationStatus();\r\n }, [showPageLoadingOverlay, hidePageLoadingOverlay, history]);\r\n\r\n if (!pageIsDisplayed) {\r\n return <>;\r\n }\r\n\r\n return (\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n\r\n
\r\n

{t('errors:errorMessage_Unauthorized')}

\r\n
\r\n\r\n {isEnvironment('local') ? (\r\n
\r\n history.push(ApplicationRoutes.SITE_ROOT)}\r\n title={t('errors:clickHereToGoHome')}\r\n />\r\n
\r\n ) : (\r\n <>\r\n )}\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default UnauthorizedPage;\r\n","import React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport SvgImage from '../../../../common-page-components/svg-image/SvgImage';\r\n\r\nconst UnlicensedPage: React.FC = () => {\r\n const { t } = useTranslation();\r\n\r\n return (\r\n
\r\n
\r\n
\r\n \r\n
\r\n\r\n
\r\n

{t('errors:errorMessage_Unlicensed')}

\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default UnlicensedPage;\r\n","import * as SignalR from '@microsoft/signalr';\r\nimport { getConfig } from '../../utils/config';\r\nimport { AuthenticationService } from '../authentication/authentication-service';\r\nimport { QueryHttpService } from '../query/query-http-service';\r\nimport { AxiosError } from 'axios';\r\n\r\nconst MAX_REGISTRATION_RETRIES = 3;\r\nconst REGISTRATION_RETRY_WAIT_IN_MS = 1000;\r\n\r\nexport class NotificationService {\r\n private static queryApiBaseUrl = getConfig('REACT_APP_QUERY_API_URL') as string;\r\n private static queryApiScope = getConfig('REACT_APP_MSAL_QUERY_API_SCOPE') as string;\r\n private static connection: SignalR.HubConnection;\r\n private static notificationHandlers: Map<\r\n string,\r\n (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => Promise\r\n > = new Map();\r\n\r\n public static async connect(): Promise {\r\n if (\r\n NotificationService.connection &&\r\n NotificationService.connection.state === SignalR.HubConnectionState.Connected\r\n ) {\r\n return;\r\n }\r\n\r\n NotificationService.connection = new SignalR.HubConnectionBuilder()\r\n .withUrl(`${NotificationService.queryApiBaseUrl}/notifications`, {\r\n headers: {\r\n AppAuth: AuthenticationService.getAuthToken()!,\r\n },\r\n accessTokenFactory: async () => {\r\n const accessToken = await AuthenticationService.getAccessToken(\r\n NotificationService.queryApiScope,\r\n );\r\n return accessToken ?? '';\r\n },\r\n })\r\n .withAutomaticReconnect()\r\n .configureLogging(SignalR.LogLevel.Error) // Set to error so we don't get warnings for pages without handlers\r\n .build();\r\n\r\n await NotificationService.connection.start();\r\n NotificationService.connection.on('DataChanged', NotificationService.onNotificationReceived);\r\n NotificationService.connection.on('EntityFrozen', NotificationService.onNotificationReceived);\r\n }\r\n\r\n public static disconnect(): void {\r\n NotificationService.connection?.stop();\r\n }\r\n\r\n public static onReconnecting(callback: (error: Error | undefined) => void): void {\r\n NotificationService.connection?.onreconnecting(callback);\r\n }\r\n\r\n public static offReconnecting(): void {\r\n NotificationService.connection?.off('reconnecting');\r\n }\r\n\r\n public static onReconnected(callback: () => void): void {\r\n NotificationService.connection?.onreconnected(() => {\r\n // Re-register for change notifications\r\n // NOTE: the SourceId we be normalized to lowercase, when registering, so we'll need to account for that when checking it later.\r\n NotificationService.notificationHandlers.forEach((handler, sourceId) => {\r\n NotificationService.registerForNotifications(sourceId, handler);\r\n });\r\n\r\n callback();\r\n });\r\n }\r\n\r\n public static offReconnected(): void {\r\n NotificationService.connection?.off('reconnected');\r\n }\r\n\r\n public static onClose(callback: () => void): void {\r\n NotificationService.connection?.onclose(callback);\r\n }\r\n\r\n public static offClose(): void {\r\n NotificationService.connection?.off('disconnected');\r\n }\r\n\r\n public static onAllEventsForCommandProcessed(\r\n callback: (message: CommandCompletedNotificationMessage) => void,\r\n ): void {\r\n NotificationService.connection?.on('AllEventsForCommandProcessed', callback);\r\n }\r\n\r\n public static offAllEventsForCommandProcessed(): void {\r\n NotificationService.connection?.off('AllEventsForCommandProcessed');\r\n }\r\n\r\n public static onDegradedActionStarted(\r\n callback: (message: DegradedActionStartedMessage) => void,\r\n ): void {\r\n NotificationService.connection?.on('DegradedActionStarted', callback);\r\n }\r\n\r\n public static offDegradedActionStarted(): void {\r\n NotificationService.connection?.off('DegradedActionStarted');\r\n }\r\n\r\n public static onDegradedActionFinished(\r\n callback: (message: DegradedActionFinishedMessage) => void,\r\n ): void {\r\n NotificationService.connection?.on('DegradedActionFinished', callback);\r\n }\r\n\r\n public static offDegradedActionFinished(): void {\r\n NotificationService.connection?.off('DegradedActionFinished');\r\n }\r\n\r\n public static async registerForNotifications(\r\n sourceId: string,\r\n callback: (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => void,\r\n ): Promise {\r\n // the given sourceId may or may not be normalized, so make it lowercase so when we get a notification later\r\n // that we can match it to the appropriate callback.\r\n const normalizedSourceId = sourceId.toLowerCase();\r\n\r\n if (!NotificationService.notificationHandlers.has(normalizedSourceId)) {\r\n const service = await QueryHttpService.getQueryService();\r\n let numberOfRetries = 0;\r\n\r\n // Retry registration in case of error\r\n const invokeRegistrationEndpointWithRetry = (): Promise => {\r\n return new Promise((resolve) => {\r\n const recursiveRetry = async () => {\r\n try {\r\n // If we got a successful registration, return true\r\n await service.post(`/notifications/registration?sourceId=${normalizedSourceId}`);\r\n resolve(true);\r\n } catch (error) {\r\n // If the registration HTTP call errored, retry recursively til we hit our limit\r\n if (numberOfRetries <= MAX_REGISTRATION_RETRIES) {\r\n setTimeout(() => {\r\n recursiveRetry();\r\n numberOfRetries++;\r\n }, REGISTRATION_RETRY_WAIT_IN_MS);\r\n } else {\r\n resolve(false);\r\n }\r\n }\r\n };\r\n\r\n // Invoke the recursive func\r\n recursiveRetry();\r\n });\r\n };\r\n\r\n const registrationSucceeded = await invokeRegistrationEndpointWithRetry();\r\n if (!registrationSucceeded) {\r\n throw new Error('Registration failed');\r\n }\r\n\r\n NotificationService.notificationHandlers.set(\r\n normalizedSourceId,\r\n async (message) => await callback(message),\r\n );\r\n }\r\n }\r\n\r\n public static async batchRegisterForNotifications(\r\n sourceIds: string[],\r\n callback: (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => void,\r\n ): Promise {\r\n const sourceIdsToRegister: string[] = [];\r\n sourceIds.forEach((sourceId) => {\r\n // the given sourceId may or may not be normalized, so make it lowercase so when we get a notification later\r\n // that we can match it to the appropriate callback.\r\n const normalizedSourceId = sourceId.toLowerCase();\r\n\r\n if (!NotificationService.notificationHandlers.has(normalizedSourceId)) {\r\n sourceIdsToRegister.push(normalizedSourceId);\r\n }\r\n });\r\n\r\n const service = await QueryHttpService.getQueryService();\r\n let numberOfRetries = 0;\r\n\r\n // Retry registration in case of error\r\n const invokeBatchRegistrationEndpointWithRetry = (): Promise => {\r\n return new Promise((resolve) => {\r\n const recursiveRetry = async (sourceIds: string[]) => {\r\n try {\r\n // If we got a successful registration, return true\r\n await service.post('/notifications/batch-registration', sourceIds);\r\n resolve(true);\r\n } catch (error) {\r\n // If the registration HTTP call errored, retry recursively til we hit our limit\r\n if (numberOfRetries <= MAX_REGISTRATION_RETRIES) {\r\n const requestError = error as AxiosError;\r\n setTimeout(() => {\r\n // If the registration failed only for some sourceIds, retry only failed ones. Otherwise, retry with all the sourceIds\r\n let failedSourceIds = sourceIds;\r\n if (Array.isArray(requestError.response?.data)) {\r\n failedSourceIds = requestError.response?.data as string[];\r\n }\r\n recursiveRetry(failedSourceIds);\r\n numberOfRetries++;\r\n }, REGISTRATION_RETRY_WAIT_IN_MS);\r\n } else {\r\n resolve(false);\r\n }\r\n }\r\n };\r\n\r\n // Invoke the recursive func\r\n recursiveRetry(sourceIds);\r\n });\r\n };\r\n\r\n const registrationSucceeded = await invokeBatchRegistrationEndpointWithRetry();\r\n if (!registrationSucceeded) {\r\n throw new Error('Registration failed');\r\n }\r\n\r\n sourceIdsToRegister.forEach((sourceId) => {\r\n NotificationService.notificationHandlers.set(\r\n sourceId,\r\n async (message) => await callback(message),\r\n );\r\n });\r\n }\r\n\r\n public static unregisterFromNotifications(sourceId: string): void {\r\n // the sourceId may or may not be normalized, so do so since we normalized them on registration.\r\n const normalizedSourceId = sourceId.toLowerCase();\r\n if (NotificationService.notificationHandlers.has(normalizedSourceId)) {\r\n NotificationService.notificationHandlers.delete(normalizedSourceId);\r\n }\r\n }\r\n\r\n private static onNotificationReceived(message: DataChangedNotificationMessage): void {\r\n // the sourceId may or may not be normalized, so do so since we normalized them on registration.\r\n const normalizedSourceId = message.SourceId.toLowerCase();\r\n const callback = NotificationService.notificationHandlers.get(normalizedSourceId);\r\n if (callback) {\r\n callback(message);\r\n }\r\n }\r\n}\r\n","import { sortBy } from 'lodash';\r\nimport React, { useContext, useEffect, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router';\r\nimport { Subscription } from 'rxjs';\r\nimport GeneralConstants from '../../../../constants/general';\r\nimport ApplicationRoutes from '../../../../constants/routes';\r\nimport { useObservableWithValue } from '../../../../hooks/observables/useObservable';\r\nimport {\r\n FrozenEntitiesApi,\r\n ProjectApi,\r\n RecentProjectsApi,\r\n SettingsApi,\r\n} from '../../../../services';\r\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\r\nimport { useLogger } from '../../../../services/logger/Logger';\r\nimport { NotificationService } from '../../../../services/notification/notification-service';\r\nimport { nameof } from '../../../../utils/nameof';\r\nimport { areTrimmedStringsEqual, doesStringExistInOtherString } from '../../../../utils/strings';\r\nimport BTCardsContainer, {\r\n BTCardListing,\r\n} from '../../../common-page-components/cards-container/BTCardsContainer';\r\nimport BTFloatingIconButton from '../../../common-page-components/controls/floating-icon-button/BTFloatingIconButton';\r\nimport BTFilterTree from '../../../common-page-components/filter-tree/BTFilterTree';\r\nimport {\r\n ModalExportData,\r\n NO_GROUPING_OPTION,\r\n} from '../../../common-page-components/filter-tree/BTFilterTreeSettingsModal';\r\nimport { FloatingLoadingIndicatorContext } from '../../../common-page-components/floating-loading-indicator/FloatingLoadingIndicatorContext';\r\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\r\nimport { BTDropDownListOption } from '../../../common-page-components/inputs/BTDropDownList';\r\nimport { BTRadioGroupOption } from '../../../common-page-components/inputs/BTRadioGroup';\r\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\r\nimport BTTabsContainer, { BTTabItem } from '../../../common-page-components/tabs/BTTabsContainer';\r\nimport ProjectSearchResultCard, {\r\n useProjectSearchResultCard,\r\n} from './components/ProjectSearchResultCard';\r\nimport './HomePage.scss';\r\n\r\nenum HomePageTabs {\r\n RecentProjects = 1,\r\n AllProjects = 2,\r\n}\r\n\r\ntype ProjectSearchColumns = keyof ProjectSearchResult;\r\nconst ProjectPropertyNamesToSearch: ProjectSearchColumns[] = [\r\n nameof('name'),\r\n nameof('subtitle'),\r\n nameof('owner'),\r\n nameof('architect'),\r\n nameof('address_StreetAddress'),\r\n nameof('address_AptSuiteBldg'),\r\n nameof('address_City'),\r\n nameof('address_StateOrRegion'),\r\n nameof('address_PostalCode'),\r\n];\r\n\r\nconst HomePage: React.FC = () => {\r\n const logger = useLogger();\r\n\r\n const history = useHistory();\r\n\r\n const userId = AuthenticationService.currentUserInfo?.id;\r\n\r\n const { t } = useTranslation();\r\n\r\n const { generateBTCardListing } = useProjectSearchResultCard();\r\n\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n\r\n const { showErrorNotification } = useContext(NotificationPanelContext);\r\n\r\n const [recentProjects, setRecentProjects] = useState([]);\r\n\r\n const [allProjects, setAllProjects] = useState([]);\r\n\r\n const [allProjectsHasBeenViewed, setAllProjectsHasBeenViewed] = useState(false);\r\n\r\n // Allows the user to run a search without a date filter, on the \"all projects\" tab\r\n const [\r\n allProjectsEnhancedTimeSearchIsActive,\r\n setAllProjectsEnhancedTimeSearchIsActive,\r\n ] = useState(false);\r\n\r\n const [lastSearchTextForAllProjects, setLastSearchTextForAllProjects] = useState('');\r\n\r\n const tabs: BTTabItem[] = [\r\n { id: HomePageTabs.RecentProjects, name: t('home:myRecentProjects') },\r\n { id: HomePageTabs.AllProjects, name: t('home:allProjects') },\r\n ];\r\n\r\n // All available options for the filter tree grouping settings\r\n const [filterTreeGroupingDropdownOptions] = useState([\r\n {\r\n name: `(${t('home:noGrouping')})`,\r\n value: NO_GROUPING_OPTION,\r\n },\r\n {\r\n name: t('home:projectFieldName_Owner'),\r\n value: nameof('owner'),\r\n },\r\n {\r\n name: t('home:projectFieldName_Architect'),\r\n value: nameof('architect'),\r\n },\r\n {\r\n name: t('home:projectFieldName_City'),\r\n value: nameof('address_City'),\r\n },\r\n {\r\n name: t('home:projectFieldName_State'),\r\n value: nameof('address_StateOrRegion'),\r\n },\r\n ]);\r\n\r\n const [availableRadioButtonOptions] = useState([\r\n {\r\n label: `${t('general:last')} 30 ${t('general:days')}`,\r\n value: 30,\r\n },\r\n {\r\n label: `${t('general:last')} 60 ${t('general:days')}`,\r\n value: 60,\r\n },\r\n {\r\n label: `${t('general:last')} 90 ${t('general:days')}`,\r\n value: 90,\r\n },\r\n ]);\r\n\r\n const [bidDayApplicationEntityIsFrozen, setBidDayApplicationEntityIsFrozen] = useState(\r\n false,\r\n );\r\n const [systemSettingsEntityIsFrozen, setSystemSettingsEntityIsFrozen] = useState(false);\r\n\r\n const [currentTab, setCurrentTab] = useState(1);\r\n\r\n const [openDropdownRecordId, setOpenDropdownRecordId] = useState();\r\n\r\n const [selectedFilters_RecentProjects, setSelectedFilters_RecentProjects] = useState<\r\n Record[]\r\n >([{}]);\r\n\r\n const [selectedFilters_AllProjects, setSelectedFilters_AllProjects] = useState<\r\n Record[]\r\n >([{}]);\r\n\r\n // The selected settings data to pass to the modal\r\n const [selectedModalData_RecentProjects, setSelectedModalData_RecentProjects] = useState<\r\n ModalExportData\r\n >({\r\n value1: NO_GROUPING_OPTION,\r\n value2: NO_GROUPING_OPTION,\r\n });\r\n\r\n const [selectedModalData_AllProjects, setSelectedModalData_AllProjects] = useState<\r\n ModalExportData\r\n >({\r\n selectedRadioButtonValue: undefined,\r\n value1: NO_GROUPING_OPTION,\r\n value2: NO_GROUPING_OPTION,\r\n });\r\n\r\n // The property of the project that we display in the treeview for each selectable item\r\n const [filterDisplayProperty_RecentProjects, setFilterDisplayProperty_RecentProjects] = useState<\r\n keyof ProjectSearchResult\r\n >(nameof('name'));\r\n\r\n // The property of the project that we display in the treeview for each selectable item\r\n const [filterDisplayProperty_AllProjects, setFilterDisplayProperty_AllProjects] = useState<\r\n keyof ProjectSearchResult\r\n >(nameof('name'));\r\n\r\n // The available values for the treeview filters\r\n const [\r\n filterGroupingProperties_RecentProjects,\r\n setFilterGroupingProperties_RecentProjects,\r\n ] = useState<(keyof ProjectSearchResult)[]>([]);\r\n\r\n // The available values for the treeview filters\r\n const [filterGroupingProperties_AllProjects, setFilterGroupingProperties_AllProjects] = useState<\r\n (keyof ProjectSearchResult)[]\r\n >([]);\r\n\r\n const [\r\n filterGroupingPropertiesSummary_RecentProjects,\r\n setFilterGroupingPropertiesSummary_RecentProjects,\r\n ] = useState<(keyof ProjectSearchResult)[]>([]);\r\n\r\n const [\r\n filterGroupingPropertiesSummary_AllProjects,\r\n setFilterGroupingPropertiesSummary_AllProjects,\r\n ] = useState<(keyof ProjectSearchResult)[]>([]);\r\n\r\n const currentUserInfo = AuthenticationService.currentUserInfo;\r\n\r\n const userIsProjectAdmin = currentUserInfo?.userIsProjectAdmin() ?? false;\r\n\r\n const [signalRBroadcast_Settings$, onSignalRBroadcast_Settings] = useObservableWithValue<\r\n DataChangedNotificationMessage | EntityFrozenNotificationMessage\r\n >();\r\n\r\n const { showFloatingLoadingIndicator_Green, hideFloatingLoadingIndicator_Green } = useContext(\r\n FloatingLoadingIndicatorContext,\r\n );\r\n\r\n // Initial data load\r\n useEffect(() => {\r\n const initializeData = async () => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // Get the frozen status of the bid day application\r\n const bidDayApplicationEntityIsFrozenResult = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION,\r\n );\r\n\r\n setBidDayApplicationEntityIsFrozen(bidDayApplicationEntityIsFrozenResult);\r\n\r\n // Get the frozen status of the system settings\r\n const systemSettingsEntityIsFrozenResult = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n );\r\n\r\n setSystemSettingsEntityIsFrozen(systemSettingsEntityIsFrozenResult);\r\n\r\n const projectViewSettingsForUser_Recent = !userId\r\n ? null\r\n : await SettingsApi.getProjectViewSettings_Recent(userId);\r\n\r\n const projectViewSettingsForUser_All = !userId\r\n ? null\r\n : await SettingsApi.getProjectViewSettings_All(userId);\r\n\r\n const projectViewSettingsForUser_RecentProjects = projectViewSettingsForUser_Recent || {\r\n groupingKey1: NO_GROUPING_OPTION,\r\n groupingKey2: NO_GROUPING_OPTION,\r\n };\r\n\r\n const projectViewSettingsForUser_AllProjects = projectViewSettingsForUser_All || {\r\n isAllProjects: true,\r\n dateRange: availableRadioButtonOptions[0].value,\r\n groupingKey1: NO_GROUPING_OPTION,\r\n groupingKey2: NO_GROUPING_OPTION,\r\n };\r\n\r\n const availableOptions = filterTreeGroupingDropdownOptions.map((v) => v.value);\r\n\r\n // Recent projects\r\n const groupingKey1_RecentProjects =\r\n projectViewSettingsForUser_RecentProjects.groupingKey1 || NO_GROUPING_OPTION;\r\n const groupingKey2_RecentProjects =\r\n projectViewSettingsForUser_RecentProjects.groupingKey2 || NO_GROUPING_OPTION;\r\n\r\n const valuesAreValid_RecentProjects =\r\n availableOptions.includes(groupingKey1_RecentProjects) &&\r\n availableOptions.includes(groupingKey2_RecentProjects) &&\r\n !(\r\n groupingKey1_RecentProjects === NO_GROUPING_OPTION &&\r\n groupingKey2_RecentProjects !== NO_GROUPING_OPTION\r\n );\r\n\r\n if (valuesAreValid_RecentProjects) {\r\n setSelectedModalData_RecentProjects({\r\n selectedRadioButtonValue: undefined,\r\n value1: projectViewSettingsForUser_RecentProjects.groupingKey1 || NO_GROUPING_OPTION,\r\n value2: projectViewSettingsForUser_RecentProjects.groupingKey2 || NO_GROUPING_OPTION,\r\n });\r\n }\r\n\r\n // All projects\r\n const groupingKey1_AllProjects =\r\n projectViewSettingsForUser_AllProjects.groupingKey1 || NO_GROUPING_OPTION;\r\n const groupingKey2_AllProjects =\r\n projectViewSettingsForUser_AllProjects.groupingKey2 || NO_GROUPING_OPTION;\r\n const selectedRadioButtonValue_AllProjects =\r\n (projectViewSettingsForUser_AllProjects.dateRange as number) ||\r\n (availableRadioButtonOptions[0].value as number);\r\n\r\n const valuesAreValid_AllProjects =\r\n availableOptions.includes(groupingKey1_AllProjects) &&\r\n availableOptions.includes(groupingKey2_AllProjects) &&\r\n !(\r\n groupingKey1_AllProjects === NO_GROUPING_OPTION &&\r\n groupingKey2_AllProjects !== NO_GROUPING_OPTION\r\n );\r\n\r\n if (valuesAreValid_AllProjects) {\r\n setSelectedModalData_AllProjects({\r\n selectedRadioButtonValue: selectedRadioButtonValue_AllProjects,\r\n value1: projectViewSettingsForUser_AllProjects.groupingKey1 || NO_GROUPING_OPTION,\r\n value2: projectViewSettingsForUser_AllProjects.groupingKey2 || NO_GROUPING_OPTION,\r\n });\r\n }\r\n\r\n const recentProjectsArray = await RecentProjectsApi.getRecentProjectsForUser();\r\n\r\n setRecentProjects(recentProjectsArray);\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('home:projectsLoadError'));\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n initializeData();\r\n }, [\r\n filterTreeGroupingDropdownOptions,\r\n hidePageLoadingOverlay,\r\n showErrorNotification,\r\n showPageLoadingOverlay,\r\n t,\r\n userId,\r\n logger,\r\n availableRadioButtonOptions,\r\n ]);\r\n\r\n // Listen for Signal R project events.\r\n // NOTE: We put SignalR callback logic in observable subscription handlers because putting it directly in the useEffect\r\n // where we register things with SignalR over the network causes that code to clean up and run again when any of the dependencies change,\r\n // which can happen a LOT and cause data loss / unnecessary network activity.\r\n // When this code reruns because dependencies change, it only unsubscribes / re-subscribes to an observable, which is quick and\r\n // doesn't involve the network.\r\n // C'est la React. Viva RxJS.\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n signalRBroadcast_Settings$.subscribe(\r\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\r\n try {\r\n showFloatingLoadingIndicator_Green(t('general:syncing'));\r\n\r\n // If the project is frozen, set the frozen flag and exit\r\n if (message.hasOwnProperty(nameof('IsFrozen'))) {\r\n logger.logDebug('bidDay.onFrozenEntityNotification', message);\r\n const entityFrozenMessage = message as EntityFrozenNotificationMessage;\r\n\r\n if (entityFrozenMessage.IsFrozen) {\r\n // Set frozen entities in state\r\n // NOTE: the SourceId is normalized to lowercase, so account for that when checking.\r\n if (\r\n entityFrozenMessage.SourceId ===\r\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION.toLowerCase()\r\n ) {\r\n setBidDayApplicationEntityIsFrozen(true);\r\n } else if (\r\n entityFrozenMessage.SourceId ===\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS.toLowerCase()\r\n ) {\r\n setSystemSettingsEntityIsFrozen(true);\r\n }\r\n } else {\r\n // TODO: Unfreeze entities\r\n // NOTE: As-is we have no way to send an \"unfrozen\" message so there's no way to test\r\n }\r\n return;\r\n }\r\n } finally {\r\n // Delay turning off the loading indicator slightly, since this code can run very fast at times\r\n // and we don't want things to flicker too fast where the user doesn't see it (it's beautiful and\r\n // deserves to be seen, dammit)\r\n setTimeout(() => {\r\n hideFloatingLoadingIndicator_Green();\r\n }, 500);\r\n }\r\n },\r\n ),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [\r\n hideFloatingLoadingIndicator_Green,\r\n hidePageLoadingOverlay,\r\n logger,\r\n showFloatingLoadingIndicator_Green,\r\n signalRBroadcast_Settings$,\r\n t,\r\n ]);\r\n\r\n // Register for settings change notifications\r\n useEffect(() => {\r\n const registerForSettingsChangeNotifications = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // NOTE: the SourceId we be normalized to lowercase, when registering, so we'll need to account for that when checking it later.\r\n await NotificationService.registerForNotifications(\r\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION,\r\n (message) => onSignalRBroadcast_Settings(message),\r\n );\r\n\r\n logger.logDebug(\r\n `registered notification group: ${GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION}`,\r\n );\r\n\r\n // NOTE: the SourceId we be normalized to lowercase, when registering, so we'll need to account for that when checking it later.\r\n await NotificationService.registerForNotifications(\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n (message) => onSignalRBroadcast_Settings(message),\r\n );\r\n\r\n logger.logDebug(\r\n `registered notification group: ${GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS}`,\r\n );\r\n } catch (error) {\r\n logger.logError(error);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n registerForSettingsChangeNotifications();\r\n\r\n return () => {\r\n [\r\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION,\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n ].forEach((currSourceId) => {\r\n logger.logDebug(`unregistered notification group: ${currSourceId}`);\r\n\r\n NotificationService.unregisterFromNotifications(currSourceId);\r\n });\r\n };\r\n }, [hidePageLoadingOverlay, logger, onSignalRBroadcast_Settings, showPageLoadingOverlay]);\r\n\r\n useEffect(() => {\r\n const newValue = [\r\n selectedModalData_RecentProjects.value1,\r\n selectedModalData_RecentProjects.value2,\r\n ].filter((m) => m !== NO_GROUPING_OPTION) as (keyof ProjectSearchResult)[];\r\n\r\n setFilterGroupingPropertiesSummary_RecentProjects(newValue);\r\n\r\n // If no groupings are provided, use a default display property\r\n if (!newValue.length) {\r\n setFilterDisplayProperty_RecentProjects(nameof('name'));\r\n setFilterGroupingProperties_RecentProjects([]);\r\n }\r\n // If 1 grouping is provided, use it as the display property and don't actually do any grouping\r\n else if (newValue.length === 1) {\r\n setFilterDisplayProperty_RecentProjects(newValue[0]);\r\n setFilterGroupingProperties_RecentProjects([]);\r\n }\r\n // If 2 groupings are provided, use the second as the display property and only group by the first property\r\n else {\r\n setFilterDisplayProperty_RecentProjects(newValue[1]);\r\n setFilterGroupingProperties_RecentProjects([newValue[0]]);\r\n }\r\n }, [selectedModalData_RecentProjects]);\r\n\r\n useEffect(() => {\r\n const newValue = [\r\n selectedModalData_AllProjects.value1,\r\n selectedModalData_AllProjects.value2,\r\n ].filter((m) => m !== NO_GROUPING_OPTION) as (keyof ProjectSearchResult)[];\r\n\r\n setFilterGroupingPropertiesSummary_AllProjects(newValue);\r\n\r\n // If no groupings are provided, use a default display property\r\n if (!newValue.length) {\r\n setFilterDisplayProperty_AllProjects(nameof('name'));\r\n setFilterGroupingProperties_AllProjects([]);\r\n }\r\n // If 1 grouping is provided, use it as the display property and don't actually do any grouping\r\n else if (newValue.length === 1) {\r\n setFilterDisplayProperty_AllProjects(newValue[0]);\r\n setFilterGroupingProperties_AllProjects([]);\r\n }\r\n // If 2 groupings are provided, use the second as the display property and only group by the first property\r\n else {\r\n setFilterDisplayProperty_AllProjects(newValue[1]);\r\n setFilterGroupingProperties_AllProjects([newValue[0]]);\r\n }\r\n }, [selectedModalData_AllProjects]);\r\n\r\n const onModalDataChange = async (\r\n modalExportData: ModalExportData,\r\n settingsType: 'recent' | 'all',\r\n ) => {\r\n if (settingsType === 'recent') {\r\n setSelectedModalData_RecentProjects({\r\n selectedRadioButtonValue: undefined,\r\n value1: modalExportData.value1,\r\n value2: modalExportData.value2,\r\n });\r\n } else {\r\n const currSelectedRadioButtonValue = selectedModalData_AllProjects.selectedRadioButtonValue;\r\n\r\n setSelectedModalData_AllProjects({\r\n selectedRadioButtonValue: modalExportData.selectedRadioButtonValue,\r\n value1: modalExportData.value1,\r\n value2: modalExportData.value2,\r\n });\r\n\r\n // If the date range filter changed, we pull all projects that meet the new criteria\r\n if (currSelectedRadioButtonValue !== modalExportData.selectedRadioButtonValue) {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n const allProjectsArray = await ProjectApi.searchAllProjects(\r\n modalExportData.selectedRadioButtonValue as number,\r\n encodeURIComponent(lastSearchTextForAllProjects),\r\n );\r\n\r\n setAllProjects(allProjectsArray);\r\n } catch {\r\n showErrorNotification(t('general:error'), t('home:projectsLoadError'));\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n }\r\n }\r\n\r\n const isAllProjects = settingsType === 'all';\r\n\r\n // Save the user's selected groupings to the server.\r\n // NOTE: There is no need to await this call / handle errors because a failure isn't catastrophic.\r\n try {\r\n SettingsApi.updateProjectViewSettings({\r\n groupingKey1:\r\n modalExportData.value1 === NO_GROUPING_OPTION ? null : (modalExportData.value1 as string),\r\n\r\n groupingKey2:\r\n modalExportData.value2 === NO_GROUPING_OPTION ? null : (modalExportData.value2 as string),\r\n\r\n dateRange: isAllProjects ? (modalExportData.selectedRadioButtonValue as number) : null,\r\n isAllProjects,\r\n });\r\n } catch {}\r\n };\r\n\r\n const onSelectedFiltersChange = (\r\n projectType: 'recent' | 'all',\r\n selectedFilters: Record[],\r\n ) => {\r\n if (projectType === 'recent') {\r\n setSelectedFilters_RecentProjects(selectedFilters);\r\n } else {\r\n setSelectedFilters_AllProjects(selectedFilters);\r\n }\r\n };\r\n\r\n const getProjectsCardsListings = (projectType: 'recent' | 'all'): BTCardListing[] => {\r\n const filteredProjects =\r\n projectType === 'recent'\r\n ? getFilteredProjects(recentProjects, selectedFilters_RecentProjects)\r\n : getFilteredProjects(allProjects, selectedFilters_AllProjects);\r\n\r\n const canUserEditOrDeleteProject = (project: ProjectSearchResult): boolean => {\r\n const userIsProjectAdmin = doesStringExistInOtherString(\r\n project.projectAdmins,\r\n currentUserInfo!.email,\r\n );\r\n\r\n // If the project is open and the user is an admin, return true\r\n return !project.isClosed && userIsProjectAdmin;\r\n };\r\n\r\n return filteredProjects.map((currProject) => {\r\n return generateBTCardListing(\r\n currProject,\r\n {\r\n if (openDropdownRecordId === currProject.id) {\r\n setOpenDropdownRecordId('');\r\n } else {\r\n setOpenDropdownRecordId(currProject.id);\r\n }\r\n }}\r\n userCanEditOrDeleteProject={\r\n !bidDayApplicationEntityIsFrozen &&\r\n !systemSettingsEntityIsFrozen &&\r\n canUserEditOrDeleteProject(currProject)\r\n }\r\n userCanCopyProject={\r\n !bidDayApplicationEntityIsFrozen && !systemSettingsEntityIsFrozen && userIsProjectAdmin\r\n }\r\n matchStartOfWord={projectType === 'all'}\r\n />,\r\n );\r\n });\r\n };\r\n\r\n const onSearchCallback_AllProjects = async (\r\n searchText: string,\r\n ignoreDateRange: boolean,\r\n ): Promise => {\r\n setLastSearchTextForAllProjects(searchText);\r\n\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n setAllProjectsEnhancedTimeSearchIsActive(ignoreDateRange);\r\n\r\n // NOTE: We pass 0 to search all projects\r\n let allProjectsArray = await ProjectApi.searchAllProjects(\r\n ignoreDateRange ? 0 : (selectedModalData_AllProjects.selectedRadioButtonValue as number),\r\n encodeURIComponent(searchText),\r\n );\r\n\r\n // Note: Projects with properties that contain the search text could be ranked before the ones with properties equal\r\n // to the search text. We want to move the projects that have properties equal to the search text to the top of the list\r\n if (searchText) {\r\n const exactMatchProjects = new Array();\r\n\r\n // Compare the search text with all the project search columns\r\n allProjectsArray.forEach((currentResult, index, projectsArray) => {\r\n for (const propertyName of ProjectPropertyNamesToSearch) {\r\n if (\r\n currentResult[propertyName]?.toString().toLowerCase() === searchText.toLowerCase()\r\n ) {\r\n exactMatchProjects.push(currentResult);\r\n projectsArray.splice(index, 1);\r\n break;\r\n }\r\n }\r\n });\r\n\r\n // Maintain the order of rest of the search results\r\n allProjectsArray = exactMatchProjects.concat(allProjectsArray);\r\n }\r\n\r\n setAllProjects(allProjectsArray);\r\n } catch {\r\n showErrorNotification(t('general:error'), t('home:projectsLoadError'));\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n const getFrozenEntitiesNames = (): string[] => {\r\n let returnValue: string[] = [];\r\n\r\n if (bidDayApplicationEntityIsFrozen) {\r\n returnValue.push(t('general:applicationSettings'));\r\n }\r\n\r\n if (systemSettingsEntityIsFrozen) {\r\n returnValue.push(t('general:systemSettings'));\r\n }\r\n\r\n returnValue = sortBy(returnValue, (v) => v);\r\n\r\n return returnValue;\r\n };\r\n\r\n const frozenEntitiesNameStrings = getFrozenEntitiesNames();\r\n\r\n return (\r\n
\r\n
\r\n \r\n\r\n {frozenEntitiesNameStrings.length > 0 ? (\r\n
\r\n
\r\n \r\n
\r\n
\r\n ) : (\r\n <>\r\n )}\r\n\r\n
\r\n {\r\n setCurrentTab(selectedTabId);\r\n\r\n // If this is the first time the user is navigating to the \"All Projects\" tab, we want to automatically run the search\r\n if (!allProjectsHasBeenViewed && selectedTabId === HomePageTabs.AllProjects) {\r\n setAllProjectsHasBeenViewed(true);\r\n onSearchCallback_AllProjects('', false);\r\n }\r\n }}\r\n >\r\n {/* NOTE: We want to display both recent / all tabs but hide one with CSS, so we don't have any jumpiness */}\r\n
\r\n
\r\n \r\n onModalDataChange(modalExportData, 'recent')\r\n }\r\n onSelectedFiltersChange={(v) => onSelectedFiltersChange('recent', v)}\r\n />\r\n
\r\n\r\n
\r\n \r\n
\r\n
\r\n\r\n
\r\n
\r\n \r\n onModalDataChange(modalExportData, 'all')\r\n }\r\n onSelectedFiltersChange={(v) => onSelectedFiltersChange('all', v)}\r\n availableRadioButtonOptions={availableRadioButtonOptions}\r\n selectedRadioButtonOptionSuffix={t('general:days')}\r\n />\r\n
\r\n\r\n
\r\n onSearchCallback_AllProjects(searchText, false)}\r\n jsxToShowAboveSearchResults={\r\n !allProjectsEnhancedTimeSearchIsActive ? (\r\n
\r\n
\r\n {t('home:noProjectsFound_DateFilterActive_Message1')} \r\n {\r\n setAllProjectsEnhancedTimeSearchIsActive(true);\r\n onSearchCallback_AllProjects(lastSearchTextForAllProjects, true);\r\n }}\r\n >\r\n {t('home:noProjectsFound_DateFilterActive_Message2')}\r\n \r\n
\r\n
\r\n ) : (\r\n
\r\n
\r\n {t('home:noProjectsFound_DateFilterInactive_Message1')} \r\n {\r\n setAllProjectsEnhancedTimeSearchIsActive(false);\r\n onSearchCallback_AllProjects(lastSearchTextForAllProjects, false);\r\n }}\r\n >\r\n {t('home:noProjectsFound_DateFilterInactive_Message2')}\r\n \r\n
\r\n
\r\n )\r\n }\r\n />\r\n
\r\n
\r\n \r\n
\r\n
\r\n\r\n {userIsProjectAdmin ? (\r\n {\r\n history.push(ApplicationRoutes.PROJECT);\r\n }}\r\n tooltip={t('project:addProject')}\r\n disabled={systemSettingsEntityIsFrozen || bidDayApplicationEntityIsFrozen}\r\n />\r\n ) : (\r\n <>\r\n )}\r\n
\r\n );\r\n};\r\n\r\nconst getFilteredProjects = (\r\n projectsToFilter: ProjectSearchResult[],\r\n filtersToApply: Record[],\r\n): ProjectSearchResult[] => {\r\n const returnValue = projectsToFilter.filter((currProject) => {\r\n let currProjectMatchesAnyFilterCriteria = false;\r\n\r\n // The selected filters array is an array of key / value pairs so we can easily look things up dynamically\r\n // in the source data\r\n for (const currSelectedFilterObject of filtersToApply) {\r\n let allCurrFilterCriteriaWasMatched = true;\r\n\r\n for (const currKey of Object.keys(currSelectedFilterObject)) {\r\n const currFilterKeyValue = currSelectedFilterObject[currKey] || '';\r\n if (\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n !areTrimmedStringsEqual((currProject as any)[currKey], currFilterKeyValue)\r\n ) {\r\n allCurrFilterCriteriaWasMatched = false;\r\n }\r\n }\r\n\r\n if (allCurrFilterCriteriaWasMatched) {\r\n currProjectMatchesAnyFilterCriteria = true;\r\n break;\r\n }\r\n }\r\n\r\n return currProjectMatchesAnyFilterCriteria;\r\n });\r\n\r\n return returnValue;\r\n};\r\n\r\nexport default HomePage;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { clone, groupBy, orderBy, sortBy, sum } from 'lodash';\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Collapse, Input } from 'reactstrap';\nimport GeneralConstants from '../../../constants/general';\nimport { nameof } from '../../../utils/nameof';\nimport { escapeStringForRegExp } from '../../../utils/strings';\nimport './BTCardsContainer.scss';\n\nexport interface BTCardListing {\n cardJSX: JSX.Element;\n searchData: string[];\n sortValue: string | Date;\n sortValue2?: string | Date;\n groupValue?: string;\n}\n\ntype BTCardsContainerSortDirection = 'ascending' | 'descending';\n\nconst BTCardsContainerContext = React.createContext({\n searchText: '' as string | null,\n});\n\ninterface Props {\n cardListings: BTCardListing[];\n enableSearch?: boolean;\n enableSort?: boolean;\n numberOfCardsPerRow?: number;\n recordsNotFoundMessage?: string;\n sortDirection?: BTCardsContainerSortDirection;\n inputPlaceholderText?: string;\n searchType?: 'pinwheel' | 'submission';\n onSearchCallback?: (searchText: string) => void;\n minSearchTextLength?: number;\n jsxToShowAboveSearchResults?: JSX.Element; // Optional JSX we can shoehorn above the search results\n}\n\ninterface GroupedReactElements {\n groupKey: string;\n cardListings: BTCardListing[];\n isOpen: boolean;\n}\n\nconst BTCardsContainer: React.FC = (props) => {\n const searchType = props.searchType ?? 'pinwheel';\n const minSearchTextLength = props.minSearchTextLength ?? 2;\n const enableSort = props.enableSort ?? true;\n\n const { t } = useTranslation();\n\n const [searchText, setSearchText] = useState('');\n\n const [filteredCards, setFilteredCards] = useState([]);\n\n const [allCards, setAllCards] = useState([]);\n\n const allCardsLastValue = useRef([]);\n\n useEffect(() => {\n setAllCards(props.cardListings);\n }, [props.cardListings]);\n\n useEffect(() => {\n if (allCardsLastValue.current !== allCards && props.searchType === 'submission') {\n allCardsLastValue.current = allCards;\n setFilteredCards(filterCards(allCards, searchText, enableSort, props.sortDirection));\n }\n }, [allCards, props.searchType, enableSort, props.sortDirection, searchText]);\n\n let columnsCssClass = '';\n switch (props.numberOfCardsPerRow) {\n case 1:\n columnsCssClass = 'col-lg-12';\n break;\n case 3:\n columnsCssClass = 'col-lg-4';\n break;\n case 4:\n columnsCssClass = 'col-lg-3';\n break;\n case 2:\n default:\n columnsCssClass = 'col-lg-6';\n break;\n }\n\n const setFilteredCardsArray = useCallback(\n (newSearchText: string): void => {\n setFilteredCards(filterCards(allCards, newSearchText, enableSort, props.sortDirection));\n },\n [allCards, enableSort, props.sortDirection],\n );\n\n const getCardsCountString = useCallback((): string => {\n const filteredCardsCount = sum(filteredCards.map((v) => v.cardListings.length));\n\n return `${t('general:displaying')} ${filteredCardsCount} ${t('general:of')} ${allCards.length}`;\n }, [t, allCards, filteredCards]);\n\n // Update the cards when the search text changes\n useEffect(() => {\n if (props.searchType === 'submission') {\n return;\n }\n\n const cleanedUpSearchText = searchText.trim();\n\n // Delay the filtering until the user stops typing for a reasonable amount of time so it doesn't flicker with a larger collection of cards\n const filteredCardsTimeout = setTimeout(() => {\n setFilteredCardsArray(cleanedUpSearchText);\n }, 250);\n\n return (): void => {\n clearTimeout(filteredCardsTimeout);\n };\n }, [props.searchType, searchText, setFilteredCardsArray]);\n\n const onSearchSubmission = useCallback(() => {\n const cleanedUpSearchText = searchText.trim();\n\n if (\n cleanedUpSearchText.length >= minSearchTextLength &&\n searchType === 'submission' &&\n props.onSearchCallback\n ) {\n props.onSearchCallback(cleanedUpSearchText);\n\n setFilteredCardsArray(cleanedUpSearchText);\n }\n }, [minSearchTextLength, props, searchText, searchType, setFilteredCardsArray]);\n\n return (\n \n
\n {props.enableSearch ? (\n
\n
\n {\n if (e.key === GeneralConstants.KEY_ENTER) {\n onSearchSubmission();\n }\n }}\n onChange={(e): void => {\n const newSearchText = e.target.value;\n setSearchText(newSearchText);\n }}\n value={searchText}\n />\n\n
\n \n
\n\n {searchText && searchText.trim().length > 0 ? (\n {\n setSearchText('');\n }}\n >\n \n
\n ) : (\n <>\n )}\n
\n\n {searchType === 'submission' ? (\n = minSearchTextLength ? '' : 'isDisabled'\n }`}\n onClick={() => {\n onSearchSubmission();\n }}\n >\n \n
\n ) : (\n <>\n )}\n\n {allCards.length ? (\n
\n \n
\n ) : (\n <>\n )}\n \n ) : (\n <>\n )}\n\n {props.jsxToShowAboveSearchResults ? props.jsxToShowAboveSearchResults : <>}\n\n {filteredCards.length ? (\n
\n {filteredCards.map((v, i) => {\n return (\n
\n {v.groupKey ? (\n {\n // Make a copy of the cards before updating the open status of the clicked item, then update the state\n const indexOfMatchingCard = filteredCards.findIndex(\n (m) => m.groupKey === v.groupKey,\n );\n if (indexOfMatchingCard > -1) {\n const copyOfFilteredCards = clone(filteredCards);\n copyOfFilteredCards[indexOfMatchingCard].isOpen = !copyOfFilteredCards[\n indexOfMatchingCard\n ].isOpen;\n setFilteredCards(copyOfFilteredCards);\n }\n }}\n >\n \n \n \n {v.groupKey} • {v.cardListings.length}\n \n ) : (\n <>\n )}\n\n \n
\n
\n {v.cardListings.map((v2, i2) => (\n
\n {v2.cardJSX}\n
\n ))}\n
\n
\n
\n
\n );\n })}\n
\n ) : (\n <>\n )}\n\n {!allCards.length || !filteredCards.length ? (\n
\n {props.recordsNotFoundMessage || 'No records were found.'}\n
\n ) : (\n <>\n )}\n \n
\n );\n};\n\nconst BTCardsContainerHighlightableText: React.FC<{\n textToDisplay: string | null | undefined;\n matchEntireWord?: boolean;\n matchStartOfWord?: boolean;\n}> = ({ textToDisplay, matchEntireWord, matchStartOfWord }) => {\n const { searchText } = useContext(BTCardsContainerContext);\n\n textToDisplay = textToDisplay || '';\n matchEntireWord = matchEntireWord ?? false;\n matchStartOfWord = matchStartOfWord ?? false;\n\n const searchTextParts = (searchText || '')\n .split(' ')\n .filter((v) => v.length > 0)\n .map((v) => v.toLowerCase());\n\n if (!searchTextParts.length) {\n return {textToDisplay};\n }\n\n // NOTE: We create a big \"or\" expression with the regex so we can replace everything in one pass and not\n // have to loop and worry about making replacements on replacements in the text.\n const textToDisplay2 = textToDisplay.replace(\n new RegExp(\n `${matchEntireWord || matchStartOfWord ? '\\\\b' : ''}(${searchTextParts\n .map((v) => escapeStringForRegExp(v))\n .join('|')})${matchEntireWord ? '\\\\b' : ''}`,\n 'ig',\n ),\n '$1',\n );\n\n return (\n \n {/* NOTE: We output the original text to display but hide it, so it gets outputted in one HTML tag and\n doesn't cause issues with finding it via card title when we test */}\n {textToDisplay}\n \n \n );\n};\n\nconst cleanUpTextForMatching = (inputText: string | null | undefined) => {\n return (inputText || '').toLowerCase().replace(/\\s{2,}/g, ' ');\n};\n\nconst groupCards = (\n cards: BTCardListing[],\n enableSort: boolean,\n sortDirection: BTCardsContainerSortDirection,\n): GroupedReactElements[] => {\n return sortBy(\n Object.values(groupBy(cards, (v) => (v.groupValue || '').toLowerCase())),\n (v) => v[0].groupValue,\n ).map(\n (currGroup): GroupedReactElements => {\n // Make a copy of the array and its items, since we're mutating the sort values for sorting\n const copy = currGroup.map((currCardListing) => {\n const returnValue = { ...currCardListing };\n\n // Clean up the sort values if they're strings\n if (!(returnValue.sortValue instanceof Date)) {\n returnValue.sortValue = (returnValue.sortValue ?? '').trim().toLowerCase();\n }\n\n if (!(returnValue.sortValue2 instanceof Date)) {\n returnValue.sortValue2 = (returnValue.sortValue2 ?? '').trim().toLowerCase();\n }\n\n return returnValue;\n });\n\n const cardsJSX = enableSort\n ? orderBy(\n copy,\n [nameof('sortValue'), nameof('sortValue2')],\n sortDirection === 'descending' ? ['desc', 'asc'] : ['asc', 'asc'],\n )\n : copy;\n\n return {\n groupKey: copy[0].groupValue || '',\n cardListings: cardsJSX,\n isOpen: true,\n };\n },\n );\n};\n\nconst filterCards = (\n cardsToFilter: BTCardListing[],\n searchText: string,\n enableSort: boolean,\n sortDirection: BTCardsContainerSortDirection = 'ascending',\n): GroupedReactElements[] => {\n searchText = (searchText || '').trim();\n\n if (!searchText) {\n const groupedCards = groupCards(cardsToFilter, enableSort, sortDirection);\n return groupedCards;\n }\n\n const filteredCardsArray = cardsToFilter.filter((currCardData) => {\n const cardMetadata = currCardData.searchData.map((v) => cleanUpTextForMatching(v));\n\n // NOTE: This matches individual search text parts\n if (cardMetadata && Array.isArray(cardMetadata)) {\n let matchFound = false;\n const searchTextParts = searchText\n .split(' ')\n .filter((v) => v.length > 0)\n .map((v) => v.toLowerCase());\n\n searchTextParts.forEach((currSearchTextPart) => {\n cardMetadata.forEach((currMetadata) => {\n if (currMetadata.indexOf(currSearchTextPart) > -1) {\n matchFound = true;\n return false;\n }\n });\n\n if (matchFound) {\n return false;\n }\n });\n\n return matchFound;\n }\n\n return false;\n });\n\n return groupCards(filteredCardsArray, enableSort, sortDirection);\n};\n\nexport default BTCardsContainer;\n\nexport { BTCardsContainerContext, BTCardsContainerHighlightableText };\n","import { IconProp } from '@fortawesome/fontawesome-svg-core';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport React from 'react';\nimport { Button } from 'reactstrap';\nimport './BTFloatingIconButton.scss';\n\ninterface Props {\n id: string;\n buttonIcon: IconProp;\n disabled?: boolean;\n onClick: () => void;\n tooltip?: string;\n 'data-testid'?: string;\n}\n\nconst BTFloatingIconButton: React.FC = (props) => {\n return (\n
\n {/* NOTE: We put the test ID on the button itself, since that is where click events are, etc. */}\n {\n props.onClick();\n }}\n disabled={props.disabled}\n title={props.tooltip}\n data-testid={props['data-testid']}\n >\n \n \n
\n );\n};\n\nexport default BTFloatingIconButton;\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { useState } from 'react';\r\nimport { Collapse } from 'reactstrap';\r\nimport { BTFilterTreeItem, getAllBTFilterTreeItemChildren } from './BTFilterTree';\r\nimport './BTFilterTreeRow.scss';\r\n\r\ninterface Props {\r\n item: BTFilterTreeItem;\r\n level: number;\r\n selectedItems: BTFilterTreeItem[];\r\n onSelectCallback: (item: BTFilterTreeItem) => void;\r\n}\r\n\r\nconst BTFilterTreeRow: React.FC = (props) => {\r\n const [isExpanded, setIsExpanded] = useState(false);\r\n\r\n const doSelectedChildElementsExist = (): boolean => {\r\n const allChildrenIds = getAllBTFilterTreeItemChildren(props.item).map((v) => v.id);\r\n return props.selectedItems.some((v) => allChildrenIds.includes(v.id));\r\n };\r\n\r\n const isSelected = props.selectedItems.find((v) => v.id === props.item.id);\r\n\r\n const testIdParts: string[] = ['treeRowName'];\r\n\r\n if ((props.item.subItems?.length || 0) > 0) {\r\n testIdParts.push('expandableRow');\r\n }\r\n\r\n testIdParts.push(props.item.name.replace(/\\s/g, '_'));\r\n\r\n if (isSelected) {\r\n testIdParts.push('selected');\r\n }\r\n\r\n const testId = testIdParts.join('-');\r\n\r\n return (\r\n
\r\n {\r\n props.onSelectCallback(props.item);\r\n }}\r\n >\r\n 0 ? 1 : 0,\r\n }}\r\n >\r\n {\r\n if ((props.item.subItems?.length || 0) > 0) {\r\n setIsExpanded((v) => !v);\r\n\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n }}\r\n >\r\n \r\n
\r\n \r\n\r\n
{props.item.name}
\r\n \r\n\r\n \r\n {props.item.subItems?.map((v) => {\r\n return (\r\n \r\n );\r\n })}\r\n \r\n \r\n );\r\n};\r\n\r\nexport default BTFilterTreeRow;\r\n","import React from 'react';\n\nimport './Forms.scss';\n\nconst FormFooter: React.FC = (props) => {\n return
{props.children}
;\n};\n\nexport default FormFooter;\n","import {\n DropDownList,\n DropDownListBlurEvent,\n DropDownListChangeEvent,\n} from '@progress/kendo-react-dropdowns';\nimport { isEqual, sortBy } from 'lodash';\nimport React, { useState } from 'react';\nimport { generateUuid } from '../../../utils/uuid';\n\nexport interface BTDropDownListOption {\n value: unknown;\n name: string;\n}\n\ninterface Props {\n placeholderText?: string;\n label?: string;\n name: string;\n value: unknown;\n data: BTDropDownListOption[];\n onChangeHandler?: (newValue: unknown, metadata?: unknown) => void;\n onBlurHandler?: (event: DropDownListBlurEvent) => void;\n disabled?: boolean;\n tooltip?: string;\n displayValueIfNotInList?: boolean;\n className?: string;\n hasErrors?: boolean;\n}\n\nconst BTDropDownList: React.FC = ({\n name,\n value,\n placeholderText,\n label,\n onChangeHandler,\n onBlurHandler,\n tooltip,\n data,\n displayValueIfNotInList,\n className,\n hasErrors,\n ...rest\n}) => {\n const [inputIdentifier] = useState(name || generateUuid());\n\n const classNames = ['formInput', className];\n let defaultItem: BTDropDownListOption | unknown;\n if (placeholderText) {\n defaultItem = { name: placeholderText, value: null };\n }\n\n if (hasErrors) {\n classNames.push('formInputError');\n }\n\n data = sortBy(data, (v) => v.name.toLowerCase());\n\n const getSelectedValue = (): BTDropDownListOption | undefined => {\n let matchingOption = data.find((v) => isEqual(v.value, value));\n\n if (displayValueIfNotInList && !matchingOption) {\n //instead of casting to a string, we'll allow the type of whatever the value is to convert to a string whatever way it knows how to...i.e. toString, etc\n matchingOption = { name: `${value || placeholderText}`, value: value };\n }\n\n return matchingOption;\n };\n\n // NOTE: Keep the field / rest props at the top so we can override the onChange property\n return (\n
\n {label ? (\n
\n \n
\n ) : (\n <>\n )}\n\n v).join(' ')}\n {...rest}\n onOpen={(e) => {\n // When this opens on smaller screens, there is an issue with Kendo's internal positioning logic where\n // it positions the dropdown options off screen, likely due to the way our app scrolls.\n // What we can do is trigger a 'scroll' event on the window, which Kendo's component listens for and which\n // will trigger it to recalculate its position, correctly.\n // On larger screens, this code has no effect since the dropdown will likely have positioned itself correctly.\n setTimeout(() => {\n window.dispatchEvent(new CustomEvent('scroll'));\n }, 400);\n }}\n onChange={(event: DropDownListChangeEvent): void => {\n if (onChangeHandler) {\n onChangeHandler(event.target.value.value);\n }\n }}\n onBlur={(event: DropDownListBlurEvent) => {\n if (onBlurHandler) {\n onBlurHandler(event);\n }\n }}\n value={getSelectedValue()}\n ref={(e) => {\n if (inputIdentifier && e?.element && !e.element.getAttribute('data-testid')) {\n e.element.setAttribute('data-testid', inputIdentifier);\n }\n }}\n />\n
\n );\n};\nexport default BTDropDownList;\n","import { RadioGroup, RadioGroupChangeEvent } from '@progress/kendo-react-inputs';\r\nimport React, { useState } from 'react';\r\nimport { generateUuid } from '../../../utils/uuid';\r\n\r\nexport interface BTRadioGroupOption {\r\n label: string;\r\n value: string | number | null | undefined;\r\n}\r\ninterface BTRadioGroupProps {\r\n name: string;\r\n label: string;\r\n data: BTRadioGroupOption[];\r\n value: string | number | null | undefined;\r\n onChange: (event: RadioGroupChangeEvent) => void;\r\n disabled?: boolean;\r\n}\r\n\r\n// A wrapped Kendo RadioGroup element that we can use independently of Formik\r\nconst BTRadioGroup: React.FC = (props) => {\r\n const [inputIdentifier] = useState(props.name || props.label || generateUuid());\r\n\r\n return (\r\n
\r\n {props.label ? (\r\n
\r\n \r\n
\r\n ) : (\r\n <>\r\n )}\r\n\r\n props.onChange(e)}\r\n disabled={props.disabled}\r\n layout={'horizontal'}\r\n ref={(e) => {\r\n if (inputIdentifier && e?.element && !e.element.getAttribute('data-testid')) {\r\n e.element!.setAttribute('data-testid', inputIdentifier);\r\n }\r\n }}\r\n />\r\n
\r\n );\r\n};\r\n\r\nexport default BTRadioGroup;\r\n","import React, { useCallback, useContext, useState } from 'react';\r\n\r\ninterface BTModalContextInterface {\r\n modalIsDisplayed: (id: string) => boolean;\r\n setModalDisplayValue: (id: string, newValue: boolean) => void;\r\n}\r\n\r\nconst BTModalContext = React.createContext({} as BTModalContextInterface);\r\n\r\nexport const BTModalContextProvider: React.FC = (props) => {\r\n // Maintain a list of modal states for all modal instances on the page\r\n const [modalDisplayStates, setModalDisplayStates] = useState>({});\r\n\r\n const modalIsDisplayed = useCallback(\r\n (id: string) => {\r\n return modalDisplayStates[id] || false;\r\n },\r\n [modalDisplayStates],\r\n );\r\n\r\n const setModalDisplayValue = useCallback(\r\n (id: string, newValue: boolean): void => {\r\n setModalDisplayStates((modalStates) => {\r\n const modalStatesClone = { ...modalStates };\r\n\r\n // Set other modalStates to false if newValue = true\r\n if (newValue) {\r\n for (const modalId in modalStatesClone) {\r\n if (modalId !== id) {\r\n modalStatesClone[modalId] = false;\r\n }\r\n }\r\n }\r\n\r\n return { ...modalStatesClone, [id]: newValue };\r\n });\r\n },\r\n [setModalDisplayStates],\r\n );\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport const useModalContext = (): BTModalContextInterface => useContext(BTModalContext);\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport FocusTrap from 'focus-trap-react';\r\nimport React, { MutableRefObject, useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Subscription } from 'rxjs';\r\nimport GeneralConstants from '../../../constants/general';\r\nimport { ConfirmationOverlayContext } from '../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport './BTModal.scss';\r\nimport { useModalContext } from './BTModalContext';\r\n\r\ntype ModalHeights = 'default' | 'minimized' | 'maximized';\r\n\r\ninterface Props {\r\n id: string; // NOTE: This must be unique for every modal instance on a page\r\n isOpen: boolean;\r\n onModalClosing?: () => Promise;\r\n onModalClose: () => void;\r\n onCloseButtonClick?: () => void;\r\n showCloseButton?: boolean;\r\n hideModalResizeButtons?: boolean;\r\n initialModalHeight?: ModalHeights;\r\n addExtraSpaceAtBottom?: boolean;\r\n // The focus trap library we use requires we have at least one tabbable input element on the page so in cases\r\n // where we don't actually have any inputs, this flag tells the component to output a hidden one for us to satisfy\r\n // the focus trap\r\n provideFocusTrapCode?: boolean;\r\n}\r\n\r\nconst BTModal: React.FC = (props) => {\r\n const { t } = useTranslation();\r\n\r\n const { confirmationOverlaySet$ } = useContext(ConfirmationOverlayContext);\r\n\r\n const [\r\n confirmationOverlayDisplayInfoIsDisplayed,\r\n setConfirmationOverlayDisplayInfoIsDisplayed,\r\n ] = useState(false);\r\n\r\n const showCloseButton = props.showCloseButton === undefined ? true : props.showCloseButton;\r\n\r\n const hideModalResizeButtons =\r\n props.hideModalResizeButtons === undefined ? false : props.hideModalResizeButtons;\r\n\r\n const { modalIsDisplayed, setModalDisplayValue } = useModalContext();\r\n\r\n const lastOpenState = useRef(false);\r\n\r\n const btModalInnerContentRef: MutableRefObject = useRef(null);\r\n\r\n const [isClosing, setIsClosing] = useState(false);\r\n\r\n const [modalHeight, setModalHeight] = useState(\r\n props.initialModalHeight || 'default',\r\n );\r\n\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n confirmationOverlaySet$.subscribe((data) => {\r\n setConfirmationOverlayDisplayInfoIsDisplayed(data?.isDisplayed ?? false);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [confirmationOverlaySet$]);\r\n\r\n const onCloseButtonClick = async ($event: React.MouseEvent): Promise => {\r\n $event.preventDefault();\r\n $event.stopPropagation();\r\n\r\n if (props.onCloseButtonClick) {\r\n props.onCloseButtonClick();\r\n } else {\r\n // If it's provided, we await a function that tells us if we should proceed closing the modal\r\n if (props.onModalClosing) {\r\n const shouldClose = await props.onModalClosing();\r\n if (shouldClose) {\r\n setIsClosing(shouldClose);\r\n }\r\n } else {\r\n setIsClosing(true);\r\n }\r\n }\r\n };\r\n\r\n // When the props.isOpen variable changes, we want to update this particular modal's\r\n // display state in the context. We also want to set the isClosing property to animate out the modal if isOpen is false.\r\n useEffect(() => {\r\n if (lastOpenState.current !== props.isOpen) {\r\n if (props.isOpen && !modalIsDisplayed(props.id)) {\r\n setModalDisplayValue(props.id, true);\r\n\r\n // Scroll to the top of the container when it opens. We delay things\r\n // slightly so the content has time to render before we scroll.\r\n setTimeout(() => {\r\n btModalInnerContentRef.current!.scrollTo({\r\n top: 0,\r\n });\r\n }, 100);\r\n\r\n setIsClosing(false);\r\n } else if (!props.isOpen && modalIsDisplayed(props.id)) {\r\n setIsClosing(true);\r\n }\r\n\r\n lastOpenState.current = props.isOpen;\r\n }\r\n }, [props.id, props.isOpen, modalIsDisplayed, setModalDisplayValue]);\r\n\r\n // When the isClosing state variable changes to true, start a timer to set it to false after a brief timeout and\r\n // call the onModalClose callback function\r\n useEffect(() => {\r\n let timeoutObj: NodeJS.Timeout;\r\n\r\n if (isClosing) {\r\n setModalHeight('default');\r\n\r\n timeoutObj = setTimeout(() => {\r\n setIsClosing(false);\r\n setModalDisplayValue(props.id, false);\r\n\r\n props.onModalClose();\r\n }, 500);\r\n }\r\n\r\n return () => {\r\n if (timeoutObj) {\r\n clearTimeout(timeoutObj);\r\n }\r\n };\r\n // NOTE: For some reason, React complains that props isn't a dependency, but it isn't needed as one because we reference\r\n // specific props properties as dependencies.\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [isClosing, props.onModalClose]);\r\n\r\n const getCssClassesForModalContent = (): string => {\r\n switch (modalHeight) {\r\n case 'minimized':\r\n return 'minimized';\r\n\r\n case 'maximized':\r\n return 'maximized';\r\n\r\n default:\r\n return '';\r\n }\r\n };\r\n\r\n const canClick = (e: MouseEvent): boolean => {\r\n const element = e.target as HTMLElement;\r\n if (element) {\r\n // allow clicking list/droplist items\r\n return element.classList.contains('k-item');\r\n }\r\n return false;\r\n };\r\n\r\n return (\r\n <>\r\n {modalIsDisplayed(props.id) ? (\r\n \r\n \r\n
\r\n\r\n {\r\n // If this particular modal is open, when the user presses \"Alt + S\", click the \"Save\" button that is inside the modal.\r\n // NOTE: By doing things generically like this (instead of using observables or something similar) is that the modal content\r\n // code doesn't have to have any knowledge of this functionality.\r\n if (\r\n props.isOpen &&\r\n // NOTE: It is important that we don't trigger this while focus is inside an input field.\r\n // Many things do validation on change so we want to wait until the user focused in the modal itself, outside\r\n // of any input element.\r\n !(e.target as HTMLElement).matches('select,input,textarea')\r\n ) {\r\n if (e.altKey && e.key.toUpperCase() === GeneralConstants.KEY_S) {\r\n const modalSaveButton = (e.target as HTMLElement).querySelector(\r\n '[is-save-button]:not([disabled])',\r\n );\r\n\r\n // NOTE: This programmatic click event works because the user triggered this code via an action with the keydown event\r\n if (modalSaveButton) {\r\n (modalSaveButton as HTMLButtonElement).click();\r\n }\r\n }\r\n\r\n if (e.key.toUpperCase() === GeneralConstants.KEY_ESCAPE.toUpperCase()) {\r\n const modalCloseButton = (e.target as HTMLElement).querySelector(\r\n '[is-close-button]:not([disabled])',\r\n );\r\n\r\n // NOTE: This programmatic click event works because the user triggered this code via an action with the keydown event\r\n if (modalCloseButton) {\r\n (modalCloseButton as HTMLButtonElement).click();\r\n } else {\r\n const modalCloseIcon = (e.target as HTMLElement).querySelector(\r\n '.closeButton',\r\n );\r\n\r\n if (modalCloseIcon) {\r\n (modalCloseIcon as HTMLElement).click();\r\n }\r\n }\r\n }\r\n }\r\n }}\r\n >\r\n
\r\n {!hideModalResizeButtons ? (\r\n <>\r\n {\r\n setModalHeight('minimized');\r\n }}\r\n >\r\n \r\n
\r\n\r\n {\r\n setModalHeight('default');\r\n }}\r\n >\r\n \r\n \r\n\r\n {\r\n setModalHeight('maximized');\r\n }}\r\n >\r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {showCloseButton ? (\r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n \r\n\r\n {\r\n if (e) {\r\n btModalInnerContentRef.current = e;\r\n }\r\n }}\r\n >\r\n
\r\n {props.children}\r\n\r\n {/* Add in an extra element to add in some extra space below the modal content */}\r\n {props.addExtraSpaceAtBottom ? (\r\n
 
\r\n ) : (\r\n <>\r\n )}\r\n
\r\n\r\n {props.provideFocusTrapCode ? (\r\n
\r\n \r\n
\r\n ) : (\r\n <>\r\n )}\r\n \r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n \r\n );\r\n};\r\n\r\nexport default BTModal;\r\n","import React, { useCallback, useContext, useEffect, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { generateUuid } from '../../../utils/uuid';\r\nimport { ConfirmationOverlayContext } from '../confirmation-overlay/ConfirmationOverlayContext';\r\nimport BTButton from '../controls/button/BTButton';\r\nimport FormFooter from '../forms/FormFooter';\r\nimport BTDropDownList, { BTDropDownListOption } from '../inputs/BTDropDownList';\r\nimport BTRadioGroup, { BTRadioGroupOption } from '../inputs/BTRadioGroup';\r\nimport BTModal from '../modal/BTModal';\r\nimport { BTFilterTreeSettingsModalInfo } from './BTFilterTree';\r\n\r\nexport interface ModalExportData {\r\n value1: string | number;\r\n value2: string | number;\r\n selectedRadioButtonValue?: unknown;\r\n}\r\n\r\ninterface Props {\r\n modalInfo: BTFilterTreeSettingsModalInfo;\r\n selectedGroupingDropdownOptions: BTDropDownListOption[];\r\n // We output an optional radio button component that the calling code can specify the details for\r\n onModalClose: (selectedGroupingValues: ModalExportData | null) => void;\r\n initialModalDataValues: ModalExportData;\r\n availableRadioButtonOptions?: BTRadioGroupOption[];\r\n}\r\n\r\nconst BTFilterTreeSettingsModal: React.FC = (props: Props): JSX.Element => {\r\n const { t } = useTranslation();\r\n\r\n const [id] = useState(generateUuid());\r\n\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n\r\n const [modalExportData, setModalExportData] = useState({\r\n value1: NO_GROUPING_OPTION,\r\n value2: NO_GROUPING_OPTION,\r\n selectedRadioButtonValue: undefined,\r\n });\r\n\r\n const [availableDropdownOptions1, setAvailableDropdownOptions1] = useState<\r\n BTDropDownListOption[]\r\n >([]);\r\n\r\n const [availableDropdownOptions2, setAvailableDropdownOptions2] = useState<\r\n BTDropDownListOption[]\r\n >([]);\r\n\r\n // Initialize the component\r\n useEffect(() => {\r\n setAvailableDropdownOptions1([...props.selectedGroupingDropdownOptions]);\r\n\r\n setModalExportData((v) => {\r\n return {\r\n ...v,\r\n selectedRadioButtonValue:\r\n props.initialModalDataValues.selectedRadioButtonValue || undefined,\r\n value1: props.initialModalDataValues.value1 || NO_GROUPING_OPTION,\r\n value2: props.initialModalDataValues.value2 || NO_GROUPING_OPTION,\r\n };\r\n });\r\n }, [props.selectedGroupingDropdownOptions, props.initialModalDataValues]);\r\n\r\n // When the first dropdown selection changes, update the available options for the second dropdown\r\n // and update the value of the second dropdown as well if needed\r\n useEffect(() => {\r\n if (modalExportData.value1 === NO_GROUPING_OPTION) {\r\n if (modalExportData.value2 !== NO_GROUPING_OPTION) {\r\n setModalExportData((v) => {\r\n return { ...v, value1: NO_GROUPING_OPTION, value2: NO_GROUPING_OPTION };\r\n });\r\n\r\n setAvailableDropdownOptions2([...props.selectedGroupingDropdownOptions]);\r\n return;\r\n }\r\n } else {\r\n const newDropdownOptionValues = props.selectedGroupingDropdownOptions.filter(\r\n (v) => v.value !== modalExportData.value1,\r\n );\r\n\r\n setAvailableDropdownOptions2(newDropdownOptionValues);\r\n\r\n if (!newDropdownOptionValues.map((v) => v.value).includes(modalExportData.value2)) {\r\n setModalExportData((v) => {\r\n return {\r\n ...v,\r\n value1: v.value1,\r\n value2: newDropdownOptionValues[0].value as string | number,\r\n };\r\n });\r\n }\r\n }\r\n }, [props.selectedGroupingDropdownOptions, modalExportData]);\r\n\r\n const onModalClosing = useCallback((): Promise => {\r\n if (\r\n modalExportData.value1 !== props.initialModalDataValues.value1 ||\r\n modalExportData.value2 !== props.initialModalDataValues.value2 ||\r\n modalExportData.selectedRadioButtonValue !==\r\n props.initialModalDataValues.selectedRadioButtonValue\r\n ) {\r\n return new Promise((resolve) => {\r\n showConfirmationOverlay({\r\n text: t('general:discardConfirmation'),\r\n buttons: [\r\n {\r\n text: t('general:discard'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n resolve(true);\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:cancel'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n resolve(false);\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n });\r\n } else {\r\n return Promise.resolve(true);\r\n }\r\n }, [\r\n hideConfirmationOverlay,\r\n props.initialModalDataValues,\r\n modalExportData.value1,\r\n modalExportData.value2,\r\n modalExportData.selectedRadioButtonValue,\r\n showConfirmationOverlay,\r\n t,\r\n ]);\r\n\r\n const resetSelectedValuesToInitialState = () => {\r\n setModalExportData((v) => {\r\n return {\r\n selectedRadioButtonValue: props.initialModalDataValues.selectedRadioButtonValue,\r\n value1: props.initialModalDataValues.value1,\r\n value2: props.initialModalDataValues.value2,\r\n };\r\n });\r\n };\r\n\r\n return (\r\n {\r\n // NOTE: We don't do anything here, we handle everything in other callbacks\r\n }}\r\n onModalClosing={onModalClosing}\r\n onCloseButtonClick={async () => {\r\n if (await onModalClosing()) {\r\n // Reset the selected values\r\n resetSelectedValuesToInitialState();\r\n\r\n props.onModalClose(null);\r\n }\r\n }}\r\n >\r\n
\r\n

{t('home:viewSettings')}

\r\n\r\n {(props.availableRadioButtonOptions?.length || 0) > 0 ? (\r\n
\r\n
\r\n {\r\n setModalExportData((v) => {\r\n return {\r\n ...v,\r\n selectedRadioButtonValue: e.value,\r\n };\r\n });\r\n }}\r\n />\r\n
\r\n
\r\n ) : (\r\n <>\r\n )}\r\n\r\n
\r\n
\r\n {\r\n setModalExportData((v) => {\r\n return {\r\n ...v,\r\n value1: value as string | number,\r\n value2: value === NO_GROUPING_OPTION ? NO_GROUPING_OPTION : v.value2,\r\n };\r\n });\r\n }}\r\n />\r\n
\r\n\r\n
\r\n {modalExportData.value1 !== NO_GROUPING_OPTION ? (\r\n {\r\n setModalExportData((v) => {\r\n return {\r\n ...v,\r\n value1: v.value1,\r\n value2: value as string | number,\r\n };\r\n });\r\n }}\r\n />\r\n ) : (\r\n <>\r\n )}\r\n
\r\n
\r\n\r\n
\r\n
\r\n {\r\n setModalExportData((v) => {\r\n return {\r\n selectedRadioButtonValue:\r\n (props.availableRadioButtonOptions?.length || 0) > 0\r\n ? props.availableRadioButtonOptions![0].value\r\n : undefined,\r\n value1: NO_GROUPING_OPTION,\r\n value2: NO_GROUPING_OPTION,\r\n };\r\n });\r\n }}\r\n />\r\n
\r\n
\r\n \r\n
\r\n {\r\n props.onModalClose(modalExportData);\r\n }}\r\n disabled={\r\n props.initialModalDataValues.value1 === modalExportData.value1 &&\r\n props.initialModalDataValues.value2 === modalExportData.value2 &&\r\n props.initialModalDataValues.selectedRadioButtonValue ===\r\n modalExportData.selectedRadioButtonValue\r\n }\r\n />\r\n\r\n => {\r\n if (await onModalClosing()) {\r\n // Reset the selected values\r\n resetSelectedValuesToInitialState();\r\n\r\n props.onModalClose(null);\r\n }\r\n }}\r\n />\r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n );\r\n};\r\n\r\nexport const NO_GROUPING_OPTION = -1;\r\n\r\nexport default BTFilterTreeSettingsModal;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport { groupBy, isEqual, sortBy, uniqBy } from 'lodash';\r\nimport React, { useCallback, useEffect, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { BTDropDownListOption } from '../inputs/BTDropDownList';\r\nimport { BTRadioGroupOption } from '../inputs/BTRadioGroup';\r\nimport './BTFilterTree.scss';\r\nimport BTFilterTreeRow from './BTFilterTreeRow';\r\nimport BTFilterTreeSettingsModal, { ModalExportData } from './BTFilterTreeSettingsModal';\r\n\r\nexport interface BTFilterTreeItem {\r\n id: string;\r\n name: string;\r\n subItems?: BTFilterTreeItem[];\r\n groupingProperties: string[];\r\n groupingPropertiesValues: string[];\r\n}\r\n\r\nexport interface BTFilterTreeSettingsModalInfo {\r\n isOpen: boolean;\r\n}\r\n\r\ninterface Props {\r\n items: T[];\r\n groupingProperties: (keyof T)[];\r\n // We let the calling code specify what the summary grouping properties are and just display them in this component.\r\n // We do this so the calling code can display something like \"State\" / \"City\" as the 2 summary groupings, but in the code,\r\n // actually have a single grouping by \"State\" and use \"City\" as the display property.\r\n summaryGroupingProperties: (keyof T)[];\r\n displayProperty: keyof T;\r\n isMultiSelect: boolean;\r\n showAllOption: boolean;\r\n userCanChangeFilters: boolean;\r\n disabledFiltersMessage?: string; // A message we show to the user to tell them why the option to open the filters is disabled\r\n availableGroupingDropdownOptions: BTDropDownListOption[];\r\n initialSelectedGroupingValues: ModalExportData;\r\n onSelectedGroupingValuesChange: (selectedGroupingValues: ModalExportData) => void;\r\n onSelectedFiltersChange: (selectedFilters: Record[]) => void;\r\n availableRadioButtonOptions?: BTRadioGroupOption[];\r\n selectedRadioButtonOptionSuffix?: string; // A suffix that we use when we display the selected value of the radio button options\r\n}\r\n\r\nconst BTFilterTree = function (props: Props): JSX.Element {\r\n const { t } = useTranslation();\r\n\r\n const [allOption] = useState({\r\n id: 'All',\r\n name: t('general:all'),\r\n groupingProperties: [],\r\n groupingPropertiesValues: [],\r\n });\r\n\r\n const [filterTreeItems, setFilterTreeItems] = useState([]);\r\n\r\n const [selectedItems, setSelectedItems] = useState(\r\n props.showAllOption ? [allOption] : [],\r\n );\r\n\r\n const [settingsModalInfo, setSettingsModalInfo] = useState({\r\n isOpen: false,\r\n });\r\n\r\n // A collection of objects that hold key/value pairs of grouping properties / selected values\r\n const [selectedItemsObjects, setSelectedItemsObjects] = useState[]>([]);\r\n\r\n useEffect(() => {\r\n const newItems = generateTreeViewItemFromGroupingProperty(\r\n t('general:noValue'),\r\n props.groupingProperties,\r\n props.displayProperty,\r\n props.items,\r\n 0,\r\n [],\r\n );\r\n\r\n setFilterTreeItems(newItems);\r\n }, [props.displayProperty, props.items, props.groupingProperties, t]);\r\n\r\n useEffect(() => {\r\n // Update the selected items if they reference filter tree items that no longer exist\r\n const filterTreeItemIds = filterTreeItems\r\n .flatMap((v) => [v, ...getAllBTFilterTreeItemChildren(v)])\r\n .map((v) => v.id);\r\n\r\n let newSelectedItems = selectedItems.filter((v) => filterTreeItemIds.includes(v.id));\r\n\r\n newSelectedItems = newSelectedItems.length ? newSelectedItems : [allOption];\r\n\r\n if (\r\n newSelectedItems.length &&\r\n !isEqual(\r\n selectedItems.map((v) => v.id),\r\n newSelectedItems.map((v) => v.id),\r\n )\r\n ) {\r\n setSelectedItems(newSelectedItems);\r\n }\r\n }, [allOption, filterTreeItems, selectedItems]);\r\n\r\n useEffect(() => {\r\n // Convert the selected treeview items to an array of objects, with the keys / values of each\r\n // object determined by the grouping keys / values for the items in this component\r\n const selectedValuesObjects: Record[] = [];\r\n\r\n selectedItems.forEach((currItem) => {\r\n const newObj: Record = {};\r\n\r\n currItem.groupingProperties.forEach((currProp, i) => {\r\n newObj[currProp] = currItem.groupingPropertiesValues[i];\r\n });\r\n\r\n selectedValuesObjects.push(newObj);\r\n });\r\n\r\n setSelectedItemsObjects(selectedValuesObjects);\r\n\r\n // TODO - if the component is a multi-select, we should recursively walk the tree and roll up\r\n // items that have the same grouping keys if all of them are selected.\r\n // Right now, we have an array of distinct selected value combinations.\r\n }, [selectedItems, props.isMultiSelect]);\r\n\r\n useEffect(() => {\r\n if (!props.isMultiSelect) {\r\n props.onSelectedFiltersChange(selectedItemsObjects);\r\n }\r\n }, [props, selectedItemsObjects]);\r\n\r\n const onSelectCallback = (item: BTFilterTreeItem) => {\r\n setSelectedItems((v) => {\r\n let copy = [...v];\r\n\r\n // TreeView Selection Logic\r\n // - If configured to be single selection:\r\n // - Any level of treeview item can be selected, including \"grouping\" items\r\n\r\n // - If configured to be multi selection:\r\n // - Only base level treeview items can be selected, but clicking \"grouping\" items will select\r\n // or deselect all children base level treeview items\r\n\r\n // - If the \"all\" option is enabled\r\n // - The \"all\" option is mutually exclusive with other options and will pre-select / drop off\r\n // the selected items automatically if needed\r\n\r\n // If the \"All\" option is shown, is selected, and was just clicked, select only it and don't deselect it\r\n if (props.showAllOption && item.id === allOption.id) {\r\n return [item];\r\n }\r\n\r\n if (!props.isMultiSelect) {\r\n // If the \"All\" option is not shown and we are deselecting the only selected option, don't let\r\n // the user deselect it\r\n const indexOfExistingItem = copy.findIndex((m) => m.id === item.id);\r\n if (!props.showAllOption && indexOfExistingItem > -1) {\r\n return copy;\r\n }\r\n\r\n copy = indexOfExistingItem > -1 ? [] : [item];\r\n } else {\r\n const allBaseLevelChildren = getAllBTFilterTreeItemChildren(item).filter(\r\n (v) => !v.subItems?.length,\r\n );\r\n\r\n // If there were no children, this is a base level item so add or remove it from the selected items\r\n if (!allBaseLevelChildren.length) {\r\n const indexOfExistingItem = copy.findIndex((m) => m.id === item.id);\r\n\r\n // If the \"All\" option is not shown and we are deselecting the only selected option, don't let\r\n // the user deselect it\r\n if (!props.showAllOption && copy.length === 1 && indexOfExistingItem > -1) {\r\n return copy;\r\n }\r\n\r\n copy = indexOfExistingItem > -1 ? copy.filter((v) => v.id !== item.id) : [...copy, item];\r\n } else {\r\n // If there were children items, select or deselect them all depending on whether they're all already selected or not\r\n const allChildrenIds = allBaseLevelChildren.map((v) => v.id);\r\n const allSelectedIds = copy.map((v) => v.id);\r\n\r\n if (!allChildrenIds.every((v) => allSelectedIds.includes(v))) {\r\n copy.push(...allBaseLevelChildren);\r\n } else {\r\n const copy2 = copy.filter((v) => !allChildrenIds.includes(v.id));\r\n\r\n // If the \"All\" option is not shown and we are deselecting the only selected option, don't let\r\n // the user deselect it\r\n if (!props.showAllOption && !copy2.length) {\r\n return copy;\r\n }\r\n\r\n copy = copy2;\r\n }\r\n }\r\n }\r\n\r\n if (props.showAllOption) {\r\n // If the \"All\" option is available, we remove it if something else is selected or add it if nothing else is selected\r\n if (copy.length > 1 && copy.find((v) => v.id === allOption.id)) {\r\n copy = copy.filter((v) => v.id !== allOption.id);\r\n } else if (!copy.length) {\r\n copy = [allOption];\r\n }\r\n }\r\n\r\n // Make sure there are only unique items in the array -- there should be, but just in case\r\n copy = uniqBy(copy, (v) => v.id);\r\n\r\n return copy;\r\n });\r\n };\r\n\r\n const onModalClose = useCallback(\r\n (selectedGroupingValues: ModalExportData | null) => {\r\n setSettingsModalInfo({\r\n isOpen: false,\r\n });\r\n\r\n // If the user closed without saving changes\r\n if (!selectedGroupingValues) {\r\n return;\r\n }\r\n\r\n props.onSelectedGroupingValuesChange(selectedGroupingValues);\r\n },\r\n\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n [props.onSelectedGroupingValuesChange],\r\n );\r\n\r\n const summaryGroupingProperties = props.summaryGroupingProperties.filter((v) => v);\r\n\r\n return (\r\n
\r\n \r\n
\r\n {\r\n if (props.userCanChangeFilters) {\r\n setSettingsModalInfo({\r\n isOpen: true,\r\n });\r\n }\r\n }}\r\n >\r\n {t('general:view')}\r\n \r\n \r\n \r\n \r\n
\r\n\r\n {summaryGroupingProperties.length ||\r\n props.initialSelectedGroupingValues.selectedRadioButtonValue ? (\r\n
\r\n {props.initialSelectedGroupingValues.selectedRadioButtonValue ? (\r\n
\r\n {`${props.initialSelectedGroupingValues.selectedRadioButtonValue} ${props.selectedRadioButtonOptionSuffix}`}\r\n
\r\n ) : (\r\n <>\r\n )}\r\n\r\n {/* If we showed the selected radio button value, add in some spacing */}\r\n {props.initialSelectedGroupingValues.selectedRadioButtonValue &&\r\n summaryGroupingProperties.length ? (\r\n
\r\n ) : (\r\n <>\r\n )}\r\n\r\n
\r\n {summaryGroupingProperties.map((v) => {\r\n const matchingItem = props.availableGroupingDropdownOptions.find(\r\n (m) => m.value === (v as string),\r\n );\r\n return (\r\n
\r\n {matchingItem?.name || ''}\r\n
\r\n );\r\n })}\r\n
\r\n
\r\n ) : (\r\n <>\r\n )}\r\n
\r\n\r\n
\r\n {props.showAllOption ? (\r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {/* If we show the all option and are not grouping things, don't show individual items */}\r\n {props.showAllOption &&\r\n props.groupingProperties.length === 0 &&\r\n props.summaryGroupingProperties.length === 0 ? (\r\n <>\r\n ) : (\r\n <>\r\n {filterTreeItems.map((v) => {\r\n return (\r\n \r\n );\r\n })}\r\n \r\n )}\r\n
\r\n\r\n {!props.isMultiSelect ? (\r\n <>\r\n ) : (\r\n
\r\n {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n setSelectedItems([allOption]);\r\n }}\r\n >\r\n {t('general:reset')}\r\n
\r\n\r\n
\r\n\r\n {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n props.onSelectedFiltersChange(selectedItemsObjects);\r\n }}\r\n >\r\n {t('general:apply')}\r\n \r\n \r\n )}\r\n\r\n \r\n \r\n );\r\n};\r\n\r\nconst getValueForSorting = (value: string) => {\r\n value = (value || '').trim().toLowerCase();\r\n return value ? value : 'zzz';\r\n};\r\n\r\n// eslint-disable-next-line @typescript-eslint/ban-types\r\nconst generateTreeViewItemFromGroupingProperty = function >(\r\n textValue_Other: string,\r\n groupingProperties: (keyof T)[],\r\n displayProperty: keyof T,\r\n currTreeGroupItems: T[],\r\n groupingPropertiesIndex: number,\r\n returnValue: BTFilterTreeItem[],\r\n): BTFilterTreeItem[] {\r\n const nextGroupingProperty = groupingProperties[groupingPropertiesIndex] as string;\r\n\r\n if (!nextGroupingProperty) {\r\n // At this point there are no more groupings so we need to get a distinct list of display values\r\n // since some of the items at this point may have the same display value\r\n const distinctItemsByDisplayProperty = sortBy(\r\n uniqBy(currTreeGroupItems, (v) =>\r\n getValueForSorting((v[displayProperty] as unknown) as string),\r\n ),\r\n (v) => getValueForSorting((v[displayProperty] as unknown) as string),\r\n );\r\n\r\n return distinctItemsByDisplayProperty.map((currItem) => {\r\n return {\r\n id: groupingProperties\r\n .map((v) => currItem[v])\r\n .concat(currItem[displayProperty])\r\n .join('|'),\r\n // NOTE: We call toString() just in case the property value wasn't a string\r\n name: (((currItem[displayProperty] as unknown) as string) || `(${textValue_Other})`)\r\n .toString()\r\n .trim(),\r\n subItems: [],\r\n // Add in the display property and the display value since we're at the end of the line here\r\n groupingProperties: [\r\n ...groupingProperties.slice(0, groupingPropertiesIndex),\r\n displayProperty,\r\n ] as string[],\r\n groupingPropertiesValues: [\r\n ...groupingProperties\r\n .slice(0, groupingPropertiesIndex)\r\n .map((currProp) => currItem[currProp]),\r\n currItem[displayProperty],\r\n ] as string[],\r\n };\r\n });\r\n }\r\n\r\n const groupedItems = groupBy(currTreeGroupItems, (v) => {\r\n return (((v as Record)[nextGroupingProperty] as string) || '')\r\n .toString() // NOTE: We call toString() just in case the property value wasn't a string\r\n .trim();\r\n });\r\n\r\n sortBy(Object.keys(groupedItems), (v) => getValueForSorting(v)).forEach((currKey) => {\r\n const newItem: BTFilterTreeItem = {\r\n id: groupingProperties\r\n .map((v) => v as string)\r\n .concat(currKey || '')\r\n .join('|'),\r\n\r\n name: currKey || `(${textValue_Other})`,\r\n subItems: [],\r\n groupingProperties: groupingProperties.slice(0, groupingPropertiesIndex + 1) as string[],\r\n groupingPropertiesValues: groupingProperties\r\n .slice(0, groupingPropertiesIndex + 1)\r\n .map((m) => {\r\n // NOTE: We can just use the first item since the properties involved in the grouping will be the same on all the items\r\n return groupedItems[currKey][0][m];\r\n }) as string[],\r\n };\r\n\r\n const itemsInCurrGrouping = groupedItems[currKey];\r\n\r\n newItem.subItems = generateTreeViewItemFromGroupingProperty(\r\n textValue_Other,\r\n groupingProperties,\r\n displayProperty,\r\n itemsInCurrGrouping,\r\n groupingPropertiesIndex + 1,\r\n [],\r\n );\r\n\r\n returnValue.push(newItem);\r\n });\r\n\r\n return returnValue;\r\n};\r\n\r\n// Recursively gets all filter tree item children and puts them into a single dimension array\r\nexport const getAllBTFilterTreeItemChildren = (\r\n currItem: BTFilterTreeItem,\r\n elementsArray: BTFilterTreeItem[] = [],\r\n): BTFilterTreeItem[] => {\r\n for (const currItem2 of currItem.subItems || []) {\r\n elementsArray.push(currItem2);\r\n\r\n if ((currItem2.subItems?.length || 0) > 0) {\r\n getAllBTFilterTreeItemChildren(currItem2, elementsArray);\r\n }\r\n }\r\n\r\n return elementsArray;\r\n};\r\n\r\nexport default BTFilterTree;\r\n","/* eslint-disable jsx-a11y/accessible-emoji */\r\nimport React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { isEnvironment } from '../../../utils/general';\r\nimport './FrozenEntityNotification.scss';\r\n\r\nconst showCoolStuff = !isEnvironment('prod') && !isEnvironment('uat');\r\n\r\n// NOTE: The user can pass in the entity type OR the title / message\r\ninterface Props {\r\n entityType?: string;\r\n title?: string;\r\n message?: string;\r\n frozenEntityNames?: string[];\r\n}\r\n\r\nconst FrozenEntityNotification: React.FC = ({\r\n entityType,\r\n title,\r\n message,\r\n frozenEntityNames,\r\n}) => {\r\n const { t } = useTranslation();\r\n\r\n return (\r\n
\r\n
\r\n
\r\n {title ? (\r\n {title}\r\n ) : (\r\n <>\r\n {t('general:frozenEntityTitle', {\r\n entityType,\r\n })}\r\n \r\n )}\r\n\r\n {showCoolStuff ? (\r\n <>\r\n 🥶\r\n \r\n ) : (\r\n <>\r\n )}\r\n
\r\n
\r\n {message ? (\r\n <>\r\n {message}\r\n\r\n {(frozenEntityNames?.length ?? 0) > 0 ? (\r\n <>\r\n {frozenEntityNames?.map((v) => {\r\n return (\r\n
\r\n {v}\r\n
\r\n );\r\n })}\r\n \r\n ) : (\r\n <>\r\n )}\r\n \r\n ) : (\r\n <>\r\n {t('general:frozenEntityText1', {\r\n entityType: entityType!.toLowerCase(),\r\n })}\r\n \r\n )}\r\n
\r\n\r\n
{t('general:frozenEntityText2')}
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default FrozenEntityNotification;\r\n","import React, { useEffect, useState } from 'react';\r\nimport './BTTabsContainer.scss';\r\n\r\nexport interface BTTabItem {\r\n id: number;\r\n name: string;\r\n}\r\n\r\ninterface Props {\r\n tabs: BTTabItem[];\r\n initialSelectedTab?: number;\r\n onTabChange: (selectedTabId: number) => void;\r\n}\r\n\r\nconst BTTabsContainer: React.FC = ({ tabs, onTabChange, initialSelectedTab, ...props }) => {\r\n // NOTE: We take an optional initial value for the selected tab\r\n const [selectedTab, setSelectedTab] = useState(initialSelectedTab || tabs[0].id);\r\n\r\n // When the initial selected tab prop changes, we want to update the internally selected tab of this component.\r\n // This flexibility allows this component to be controlled or uncontrolled.\r\n useEffect(() => {\r\n setSelectedTab((v) => {\r\n return initialSelectedTab !== undefined && v !== initialSelectedTab ? initialSelectedTab : v;\r\n });\r\n }, [initialSelectedTab]);\r\n\r\n return (\r\n <>\r\n
\r\n
\r\n {tabs.map((v, i) => {\r\n return (\r\n {\r\n setSelectedTab(v.id);\r\n onTabChange(v.id);\r\n }}\r\n >\r\n {v.name}\r\n
\r\n );\r\n })}\r\n
\r\n\r\n
{props.children}
\r\n \r\n \r\n );\r\n};\r\n\r\nexport default BTTabsContainer;\r\n","import moment from 'moment';\r\nimport { cloneDeep } from 'lodash';\r\n\r\nconst getShortDateString = (dateObj: Date | null): string => {\r\n if (!dateObj) {\r\n return '';\r\n }\r\n\r\n // NOTE: converting to UTC here because a timezone conversion would give us the wrong date\r\n // NOTE: The \"L\" date format uses the user's locale for the date format\r\n return moment.utc(dateObj).format('L');\r\n};\r\n\r\n// NOTE: using `any` here because of metaprogramming\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\n/* eslint-disable @typescript-eslint/explicit-module-boundary-types */\r\nconst getObjectWithDateStringsAsDates = (data: any): any => {\r\n const result = cloneDeep(data);\r\n\r\n if (Array.isArray(data)) {\r\n const resultArray = result as any[];\r\n return resultArray.map((r) => getObjectWithDateStringsAsDates(r));\r\n }\r\n\r\n for (const key in result) {\r\n const value = result[key];\r\n\r\n if (typeof value === 'object') {\r\n result[key] = getObjectWithDateStringsAsDates(value);\r\n continue;\r\n }\r\n\r\n const dateValue = moment(value, moment.ISO_8601);\r\n\r\n if (!dateValue.isValid()) {\r\n continue;\r\n }\r\n\r\n result[key] = dateValue.toDate();\r\n }\r\n\r\n return result;\r\n};\r\n\r\nexport { getShortDateString, getObjectWithDateStringsAsDates };\r\n","const getEEClass = (): string => {\r\n const randomNumber1 = Math.floor(Math.random() * 100) % 5;\r\n const randomNumber2 = Math.floor(Math.random() * 100) % 5;\r\n const returnValue = ['ee-hot-air-balloon'];\r\n\r\n if (randomNumber1 === 1) {\r\n returnValue.push('balloon-position1');\r\n } else if (randomNumber1 === 2) {\r\n returnValue.push('balloon-position2');\r\n } else if (randomNumber1 === 3) {\r\n returnValue.push('balloon-position3');\r\n } else if (randomNumber1 === 4) {\r\n returnValue.push('balloon-position4');\r\n }\r\n\r\n if (randomNumber2 === 1) {\r\n returnValue.push('balloon2');\r\n } else if (randomNumber2 === 2) {\r\n returnValue.push('balloon3');\r\n } else if (randomNumber2 === 3) {\r\n returnValue.push('balloon4');\r\n } else if (randomNumber2 === 4) {\r\n returnValue.push('balloon5');\r\n }\r\n\r\n return returnValue.join(' ');\r\n};\r\n\r\nexport { getEEClass };\r\n","import { IconProp } from '@fortawesome/fontawesome-svg-core';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport React from 'react';\nimport { Button } from 'reactstrap';\nimport './BTIconButton.scss';\n\ninterface Props {\n icon: IconProp;\n disabled?: boolean;\n onClick: () => void;\n tooltip: string;\n tabIndex?: number;\n 'data-testid'?: string;\n}\n\nconst BTIconButton: React.FC = ({ onClick, disabled, tooltip, icon, tabIndex, ...rest }) => {\n return (\n {\n onClick();\n }}\n disabled={disabled}\n title={tooltip}\n tabIndex={tabIndex}\n {...rest} // NOTE: don't remove, this is how we are passing data props like `data-testid`\n >\n \n \n );\n};\n\nexport default BTIconButton;\n","import { IconProp } from '@fortawesome/fontawesome-svg-core';\r\nimport React from 'react';\r\nimport { Card, CardBody, CardHeader } from 'reactstrap';\r\nimport { getEEClass } from '../../../utils/ee';\r\nimport { isEnvironment } from '../../../utils/general';\r\nimport { BTCardsContainerHighlightableText } from '../cards-container/BTCardsContainer';\r\nimport BTIconButton from '../controls/icon-button/BTIconButton';\r\nimport './BTCard.scss';\r\n\r\nexport type BTCardIcon = {\r\n buttonIcon: IconProp;\r\n tooltip: string;\r\n onClick: () => void;\r\n disabled?: boolean;\r\n 'data-testid'?: string;\r\n};\r\n\r\nexport interface Props {\r\n title?: string;\r\n cardIcons?: BTCardIcon[];\r\n 'data-testid'?: string;\r\n matchStartOfWord?: boolean;\r\n matchEntireWord?: boolean;\r\n}\r\n\r\nconst BTCard: React.FC = (props) => {\r\n const matchStartOfWord = props.matchStartOfWord ?? false;\r\n const matchEntireWord = props.matchEntireWord ?? false;\r\n\r\n return (\r\n \r\n {!(props.title || props.cardIcons) ? (\r\n <>\r\n ) : (\r\n \r\n
\r\n {props.title ? (\r\n
\r\n \r\n
\r\n ) : (\r\n <>\r\n )}\r\n {props.cardIcons && props.cardIcons.length ? (\r\n
\r\n {props.cardIcons.map((currCardIcon, i) => {\r\n return (\r\n \r\n );\r\n })}\r\n
\r\n ) : (\r\n <>\r\n )}\r\n
\r\n
\r\n )}\r\n\r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport default BTCard;\r\n","import { IconName, IconPrefix } from '@fortawesome/fontawesome-svg-core';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport React from 'react';\nimport './BTIconButtonToggle.scss';\n\ninterface Props {\n icon: IconName;\n prefix?: IconPrefix;\n smallToggle?: boolean;\n onClick?: (newValue: boolean, event: React.MouseEvent) => void;\n onPointerUp?: (newValue: boolean, event: React.MouseEvent) => void;\n tooltip: string;\n 'data-testid'?: string;\n value: boolean;\n className?: string;\n disabled?: boolean;\n}\n\n// TODO - this needs to be named better - realistically, it should probably replace the icon-button component,\n// but we would need to build in various functionality, like disabled state, etc.\nconst BTIconButtonToggle: React.FC = ({\n onClick,\n onPointerUp,\n tooltip,\n icon,\n prefix,\n smallToggle,\n value,\n className,\n disabled,\n ...rest\n}) => {\n const getClasses = (): string => {\n const returnValue: string[] = ['btIconButtonToggle'];\n\n if (value) {\n returnValue.push('isToggled');\n }\n\n if (smallToggle) {\n returnValue.push('smallToggle');\n }\n\n if (className) {\n returnValue.push(className);\n }\n\n if (disabled) {\n returnValue.push('disabled');\n }\n\n return returnValue.join(' ');\n };\n\n return (\n {\n if (onClick && !disabled) {\n onClick(!value, $event);\n }\n }}\n onPointerUp={($event): void => {\n if (onPointerUp && !disabled) {\n onPointerUp(!value, $event);\n }\n }}\n title={tooltip}\n {...rest}\n >\n {/* Only pass the IconPrefix/IconName array if a prefix is provided, otherwise we just pass an IconName */}\n {prefix ? : }\n \n );\n};\n\nexport default BTIconButtonToggle;\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport moment from 'moment';\r\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Link } from 'react-router-dom';\r\nimport { Dropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reactstrap';\r\nimport { getShortDateString } from '../../../../../utils/dates';\r\nimport { formatNumberAsCurrency, normalizeNullOrUndefined } from '../../../../../utils/general';\r\nimport BTCard from '../../../../common-page-components/card/BTCard';\r\nimport {\r\n BTCardListing,\r\n BTCardsContainerHighlightableText,\r\n} from '../../../../common-page-components/cards-container/BTCardsContainer';\r\nimport { ProjectApi } from '../../../../../services';\r\nimport BTIconButtonToggle from '../../../../common-page-components/controls/icon-button-toggle/BTIconButtonToggle';\r\nimport defaultProjectImage from './../../../../assets/images/default-project-image.png';\r\nimport './ProjectSearchResultCard.scss';\r\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\r\n\r\ninterface Props {\r\n project: ProjectSearchResult;\r\n projectUrl: string;\r\n projectEditUrl: string;\r\n dropdownIsOpen: boolean;\r\n onMenuButtonClick: () => void;\r\n userCanCopyProject: boolean;\r\n userCanEditOrDeleteProject: boolean;\r\n matchStartOfWord: boolean;\r\n}\r\n\r\ninterface ReturnValue {\r\n generateBTCardListing: (project: ProjectSearchResult, cardJSX: JSX.Element) => BTCardListing;\r\n}\r\n\r\nconst useProjectSearchResultCard = (): ReturnValue => {\r\n const generateBTCardListing = useCallback(\r\n (project: ProjectSearchResult, cardJSX: JSX.Element): BTCardListing => {\r\n return {\r\n searchData: [\r\n project.name || '',\r\n project.subtitle || '',\r\n project.owner || '',\r\n project.architect || '',\r\n project.address_StreetAddress || '',\r\n project.address_AptSuiteBldg || '',\r\n project.address_City || '',\r\n project.address_StateOrRegion || '',\r\n project.address_PostalCode || '',\r\n ],\r\n sortValue: project.lastAccessedDate || '',\r\n sortValue2: project.name,\r\n groupValue: '',\r\n cardJSX,\r\n };\r\n },\r\n [],\r\n );\r\n\r\n return {\r\n generateBTCardListing,\r\n };\r\n};\r\n\r\nconst ProjectSearchResultCard: React.FC = (props) => {\r\n const { t } = useTranslation();\r\n\r\n const canEditProject = props.userCanEditOrDeleteProject && !props.project.isFrozen;\r\n\r\n const [projectImageBlobUrl, setProjectImageBlobUrl] = useState();\r\n\r\n const currentProjectImageUri = useRef();\r\n\r\n const { showErrorNotification } = useContext(NotificationPanelContext);\r\n\r\n useEffect(() => {\r\n const getProjectImageUrl = async () => {\r\n if (currentProjectImageUri.current !== props.project.imageUri) {\r\n if (props.project.imageUri) {\r\n // Fetch the latest project image if there is one\r\n try {\r\n const imageBlobUrl = await ProjectApi.getProjectImageBlobUrl(\r\n props.project.id,\r\n props.project.imageUri,\r\n );\r\n\r\n setProjectImageBlobUrl(imageBlobUrl);\r\n } catch (error) {\r\n showErrorNotification(t('general:error'), t('project:projectImageLoadError'));\r\n }\r\n }\r\n\r\n currentProjectImageUri.current = props.project.imageUri;\r\n }\r\n };\r\n\r\n getProjectImageUrl();\r\n }, [projectImageBlobUrl, props.project.id, props.project.imageUri, showErrorNotification, t]);\r\n\r\n return (\r\n \r\n
\r\n
\r\n

\r\n \r\n \r\n \r\n

\r\n\r\n {/* Show the last accessed date if it's provided */}\r\n {props.project.lastAccessedDate ? (\r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {canEditProject ? (\r\n
\r\n \r\n \r\n \r\n \r\n\r\n \r\n {canEditProject ? (\r\n \r\n \r\n \r\n {t('general:edit')}\r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {/* NOTE: The copy and delete functionality is temporarily commented out since the pages they would redirect to\r\n are not implemented yet */}\r\n\r\n {/* {props.userCanCopyProject ? (\r\n \r\n \r\n {t('general:copy')}\r\n \r\n ) : (\r\n <>\r\n )} */}\r\n\r\n {/* {props.userCanEditOrDeleteProject ? (\r\n <>\r\n \r\n\r\n \r\n \r\n {t('general:delete')}\r\n \r\n \r\n ) : (\r\n <>\r\n )} */}\r\n \r\n \r\n
\r\n ) : (\r\n <>\r\n )}\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n
\r\n );\r\n};\r\n\r\nconst ProjectDetailRow: React.FC<{\r\n label: string;\r\n value: string | undefined;\r\n matchStartOfWord: boolean;\r\n}> = (props) => {\r\n const { t } = useTranslation();\r\n\r\n return (\r\n
\r\n \r\n\r\n {/* NOTE: The unit tests for this component will fail unless we have the \"aria-label\" attribute on this element, because\r\n it is not a form element and we are using the htmlFor attribute on the label above.\r\n */}\r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nconst getAreaText = (area: number | undefined, unitOfMeasure: string | undefined) => {\r\n if (normalizeNullOrUndefined(area) === null) {\r\n return '';\r\n }\r\n\r\n return `${area}${unitOfMeasure ? ' ' + unitOfMeasure : ''}`;\r\n};\r\n\r\nconst getAddressTextFromProjectSearchResult = (project: ProjectSearchResult): string => {\r\n return [\r\n `${project.address_StreetAddress || ''} ${project.address_AptSuiteBldg || ''}`.trim(),\r\n project.address_City,\r\n project.address_StateOrRegion,\r\n project.address_PostalCode,\r\n ]\r\n .map((v) => (v || '').trim())\r\n .filter((v) => v)\r\n .join(', ');\r\n};\r\n\r\nexport { useProjectSearchResultCard };\r\n\r\nexport default ProjectSearchResultCard;\r\n","const LinksConstants = {\r\n BECKTECH_WEBSITE: 'http://www.beck-technology.com',\r\n BECKTECH_COMMUNITY_WEBSITE: 'http://community.beck-technology.com',\r\n};\r\n\r\nexport default LinksConstants;\r\n","import React, { useEffect } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router-dom';\r\nimport ApplicationRoutes from '../../../../constants/routes';\r\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\r\nimport { getConfig } from '../../../../utils/config';\r\nimport BTButton from '../../../common-page-components/controls/button/BTButton';\r\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\r\nimport GeneralConstants from './../../../../constants/general';\r\nimport LinksConstants from './../../../../constants/links';\r\nimport './LoginPage.scss';\r\n\r\nconst LoginPage: React.FC = () => {\r\n const { t } = useTranslation();\r\n const history = useHistory();\r\n\r\n useEffect(() => {\r\n // if the user is already logged in, just go to the home page\r\n if (AuthenticationService.userIsAuthenticated()) {\r\n history.replace(ApplicationRoutes.HOME);\r\n }\r\n }, [history]);\r\n\r\n const getUrlForDisplay = (url: string): string => {\r\n return url.replace('http://', '');\r\n };\r\n\r\n const websiteUrl = getConfig('REACT_APP_BECKTECH_URL') || LinksConstants.BECKTECH_WEBSITE;\r\n const websiteUrlCommunity =\r\n getConfig('REACT_APP_BECKTECH_COMMUNITY_URL') || LinksConstants.BECKTECH_COMMUNITY_WEBSITE;\r\n\r\n return (\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n\r\n
\r\n \r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n To learn more about {GeneralConstants.PRODUCT_NAME_FULL} and preconstruction lifecycle\r\n data please visit our website at{' '}\r\n \r\n {getUrlForDisplay(websiteUrl)}\r\n \r\n .\r\n
\r\n
\r\n If you need assistance with {GeneralConstants.PRODUCT_NAME}, visit our online\r\n community at{' '}\r\n \r\n {getUrlForDisplay(websiteUrlCommunity)}\r\n \r\n .\r\n
\r\n
\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default LoginPage;\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class CreateBidPackageDefinitionCommand extends CommandBase {\r\n public code: string;\r\n public description: string;\r\n\r\n constructor(code: string, description: string) {\r\n super('DESTINI.BidDay.Commands.BidDaySystem.CreateBidPackageDefinition', '', 'none');\r\n this.code = code;\r\n this.description = description;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class DeleteBidPackageDefinitionCommand extends CommandBase {\r\n public code: string;\r\n\r\n constructor(code: string) {\r\n super('DESTINI.BidDay.Commands.BidDaySystem.DeleteBidPackageDefinition', '', 'none');\r\n this.code = code;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class UpdateBidPackageDefinitionCodeCommand extends CommandBase {\r\n public code: string;\r\n public updatedCode: string;\r\n\r\n constructor(number: string, updatedNumber: string) {\r\n super('DESTINI.BidDay.Commands.BidDaySystem.UpdateBidPackageDefinitionCode', '', 'none');\r\n this.code = number;\r\n this.updatedCode = updatedNumber;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class UpdateBidPackageDefinitionDescriptionCommand extends CommandBase {\r\n public code: string;\r\n public description: string;\r\n public updatedDescription: string;\r\n\r\n constructor(code: string, description: string, updatedDescription: string) {\r\n super('DESTINI.BidDay.Commands.BidDaySystem.UpdateBidPackageDefinitionDescription', '', 'none');\r\n this.code = code;\r\n this.description = description;\r\n this.updatedDescription = updatedDescription;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class CreateTradeRequirementDefinitionCommand extends CommandBase {\r\n public bidPackageCode: string;\r\n public index: number;\r\n public description: string;\r\n public requirementFulfillmentType: number;\r\n\r\n constructor(\r\n bidPackageCode: string,\r\n index: number,\r\n description: string,\r\n requirementFulfillmentType: number,\r\n ) {\r\n super(' DESTINI.BidDay.Commands.BidDaySystem.CreateTradeRequirementDefinition', '', 'none');\r\n this.bidPackageCode = bidPackageCode;\r\n this.index = index;\r\n this.description = description;\r\n this.requirementFulfillmentType = requirementFulfillmentType;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class UpdateTradeRequirementDefinitionDescriptionCommand extends CommandBase {\r\n public bidPackageCode: string;\r\n public description: string;\r\n public updatedDescription: string;\r\n\r\n constructor(bidPackageCode: string, description: string, updatedDescription: string) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateTradeRequirementDefinitionDescription',\r\n '',\r\n 'none',\r\n );\r\n this.bidPackageCode = bidPackageCode;\r\n this.description = description;\r\n this.updatedDescription = updatedDescription;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class UpdateTradeRequirementDefinitionIndexCommand extends CommandBase {\r\n public bidPackageCode: string;\r\n public description: string;\r\n public updatedIndex: number;\r\n\r\n constructor(bidPackageCode: string, description: string, updatedIndex: number) {\r\n super('DESTINI.BidDay.Commands.BidDaySystem.UpdateTradeRequirementDefinitionIndex', '', 'none');\r\n this.bidPackageCode = bidPackageCode;\r\n this.description = description;\r\n this.updatedIndex = updatedIndex;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class UpdateTradeRequirementDefinitionRequirementFulfillmentTypeCommand extends CommandBase {\r\n public bidPackageCode: string;\r\n public description: string;\r\n public requirementFulfillmentType: number;\r\n\r\n constructor(bidPackageCode: string, description: string, requirementFulfillmentType: number) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateTradeRequirementDefinitionRequirementFulfillmentType',\r\n '',\r\n 'none',\r\n );\r\n this.bidPackageCode = bidPackageCode;\r\n this.description = description;\r\n this.requirementFulfillmentType = requirementFulfillmentType;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class DeleteTradeRequirementDefinitionCommand extends CommandBase {\r\n public bidPackageCode: string;\r\n public description: string;\r\n\r\n constructor(bidPackageCode: string, description: string) {\r\n super(' DESTINI.BidDay.Commands.BidDaySystem.DeleteTradeRequirementDefinition', '', 'none');\r\n this.bidPackageCode = bidPackageCode;\r\n this.description = description;\r\n }\r\n}\r\n","import { CommandBatchBase } from '../../CommandBatchBase';\r\nimport { CreateBidPackageDefinitionCommand } from '../bid-package-definitions/create-bid-package-definition-command';\r\nimport { DeleteBidPackageDefinitionCommand } from '../bid-package-definitions/delete-bid-package-definition-command';\r\nimport { UpdateBidPackageDefinitionCodeCommand } from '../bid-package-definitions/update-bid-package-definition-code-command';\r\nimport { UpdateBidPackageDefinitionDescriptionCommand } from '../bid-package-definitions/update-bid-package-definition-description-command';\r\nimport { CreateTradeRequirementDefinitionCommand } from '../trade-requirement-definitions/create-trade-requirement-definition-command';\r\nimport { UpdateTradeRequirementDefinitionDescriptionCommand } from '../trade-requirement-definitions/update-trade-requirement-definition-description-command';\r\nimport { UpdateTradeRequirementDefinitionIndexCommand } from '../trade-requirement-definitions/update-trade-requirement-definition-index-command';\r\nimport { UpdateTradeRequirementDefinitionRequirementFulfillmentTypeCommand } from '../trade-requirement-definitions/update-trade-requirement-definition-requirement-fulfillment-type-command';\r\nimport { DeleteTradeRequirementDefinitionCommand } from './../trade-requirement-definitions/delete-trade-requirement-definition-command';\r\n\r\nexport class BidPackageMaintenanceBatchCommand extends CommandBatchBase {\r\n constructor() {\r\n super('bid-package-maintenance-batch', '/bidDaySystemSettings', 'post', [\r\n CreateBidPackageDefinitionCommand,\r\n DeleteBidPackageDefinitionCommand,\r\n UpdateBidPackageDefinitionDescriptionCommand,\r\n UpdateBidPackageDefinitionCodeCommand,\r\n CreateTradeRequirementDefinitionCommand,\r\n DeleteTradeRequirementDefinitionCommand,\r\n UpdateTradeRequirementDefinitionIndexCommand,\r\n UpdateTradeRequirementDefinitionDescriptionCommand,\r\n UpdateTradeRequirementDefinitionRequirementFulfillmentTypeCommand,\r\n ]);\r\n }\r\n}\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { clone, cloneDeep } from 'lodash';\r\nimport React, { useCallback, useState } from 'react';\r\n\r\n// NOTE: Contexts let us share state, and in this case, dispatch actions from various nested components.\r\n\r\n// NOTE: When creating reducers, it is crucial that we create deep copies of objects we are\r\n// mutating (ie. use lodash's clone() method), so we retain proper class information.\r\n\r\ninterface DispatchManagerContextInterface {\r\n registerReducers: (key: string, ...reducers: DispatchManagerReducer[]) => void;\r\n unregisterReducer: (key: string, reducer: DispatchManagerReducer) => void;\r\n dispatchAction: (key: string, action: DispatchManagerDispatchAction) => void;\r\n setDispatchData: (key: string, data: unknown) => void;\r\n dispatchData: Map;\r\n getDispatchData: (dispatchDataObj: Map, key: string) => T | null;\r\n}\r\n\r\nconst DispatchManagerContext = React.createContext(\r\n {} as DispatchManagerContextInterface,\r\n);\r\n\r\nfunction getDispatchData(dispatchDataObj: Map, key: string): T | null {\r\n return (dispatchDataObj.get(key) ?? null) as T | null;\r\n}\r\n\r\nconst DispatchManagerContextProvider: React.FC = (props) => {\r\n // NOTE: The reducers and dispatch data collections are kept separate\r\n const [allDispatchData, setAllDispatchData] = useState>(new Map());\r\n\r\n const [reducers, setReducers] = useState[]>>(\r\n {},\r\n );\r\n\r\n const registerReducers = useCallback(function registerReducersFn(\r\n key: string,\r\n ...newReducers: DispatchManagerReducer[] // NOTE: The action type type parameter has to be any since we can't cast a type as unknown\r\n ): void {\r\n setReducers((existingReducers) => {\r\n // NOTE: Since we are copying the object that holds all state data, we can use the spread syntax here\r\n const existingReducersCopy = { ...existingReducers };\r\n let reducersCollectionToModify = existingReducersCopy[key] as DispatchManagerReducer<\r\n T,\r\n unknown\r\n >[];\r\n\r\n if (!reducersCollectionToModify) {\r\n reducersCollectionToModify = [];\r\n existingReducersCopy[key] = reducersCollectionToModify;\r\n }\r\n\r\n newReducers.forEach((currNewReducer) => {\r\n const reducerAlreadyExists = reducersCollectionToModify.some((v) => v === currNewReducer);\r\n if (!reducerAlreadyExists) {\r\n reducersCollectionToModify.push(currNewReducer);\r\n }\r\n });\r\n\r\n return existingReducersCopy;\r\n });\r\n }, []);\r\n\r\n const unregisterReducer = useCallback(function unregisterReducerFn(\r\n key: string,\r\n reducerToRemove: DispatchManagerReducer,\r\n ): void {\r\n setReducers((existingReducers) => {\r\n // NOTE: Since we are copying the object that holds all state data, we can use the spread syntax here\r\n const existingReducersCopy = { ...existingReducers };\r\n let reducersCollectionToModify = existingReducersCopy[key] as DispatchManagerReducer<\r\n T,\r\n unknown\r\n >[];\r\n\r\n if (reducersCollectionToModify) {\r\n const indexOfReducer = reducersCollectionToModify.findIndex((v) => v === reducerToRemove);\r\n if (indexOfReducer > -1) {\r\n const newArray = [...reducersCollectionToModify];\r\n newArray.splice(indexOfReducer, 1);\r\n reducersCollectionToModify = newArray;\r\n }\r\n }\r\n\r\n return existingReducersCopy;\r\n });\r\n },\r\n []);\r\n\r\n // NOTE: This method is meant to mutate data, not return a new object\r\n const runReducersAgainstData = useCallback(\r\n (key: string, data: unknown, action: DispatchManagerDispatchAction): unknown => {\r\n // If any reducers exist for the group, run them\r\n const matchingReducerCollection = reducers[key] as DispatchManagerReducer[];\r\n if (matchingReducerCollection) {\r\n matchingReducerCollection.forEach((currReducer) => {\r\n data = currReducer(data, action);\r\n });\r\n }\r\n\r\n return data;\r\n },\r\n [reducers],\r\n );\r\n\r\n const setDispatchData = useCallback((key: string, data: unknown) => {\r\n setAllDispatchData((existingDispatchData) => {\r\n // Clone the object with lodash so it's a deep copy\r\n const copy = clone(existingDispatchData);\r\n copy.set(key, data);\r\n return copy;\r\n });\r\n }, []);\r\n\r\n const dispatchAction = useCallback(\r\n function dispatchActionFn(\r\n key: string,\r\n action: DispatchManagerDispatchAction,\r\n ): void {\r\n setAllDispatchData((existingDispatchData) => {\r\n const dataToModify: unknown = existingDispatchData.get(key);\r\n\r\n if (dataToModify === undefined) {\r\n throw new Error(`Dispatch Action - Data for key '${key}' was not found.`);\r\n }\r\n\r\n // Clone the object with lodash so it's a deep copy\r\n let dataToModifyCopy = cloneDeep(dataToModify);\r\n dataToModifyCopy = runReducersAgainstData(key, dataToModifyCopy, action);\r\n\r\n const existingDispatchDataCopy = new Map(existingDispatchData);\r\n existingDispatchDataCopy.set(key, dataToModifyCopy);\r\n\r\n return existingDispatchDataCopy;\r\n });\r\n },\r\n [runReducersAgainstData],\r\n );\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport { DispatchManagerContext, DispatchManagerContextProvider };\r\n","export enum Feature {\n BidderOrdering = 'BidderOrdering',\n LineItemOrdering = 'LineItemOrdering',\n}\n\nexport const LocalStoragePrefix = 'Feature_';\n\nexport type FeatureFlags = {\n [name in Feature]?: boolean;\n};\n\nexport const getFeatureFlagsFromLocalStorage = (): FeatureFlags => {\n const features = Object.values(Feature);\n const flags: FeatureFlags = {};\n\n // Populate FeatureFlags obj from Feature enum vals\n features.forEach((feature) => {\n flags[feature] = false;\n });\n\n // Populate FeatureFlags obj with vals from local storage\n Object.keys(localStorage).forEach((key) => {\n // Ignore keys that don't have the expected prefix\n if (!key.startsWith(LocalStoragePrefix)) {\n return;\n }\n\n const parts = key.split(LocalStoragePrefix);\n const feature = parts[parts.length - 1] as Feature;\n\n // Ignore keys that are not part of the Feature enum\n if (!feature || !features.includes(feature)) {\n return;\n }\n\n const item = localStorage.getItem(key);\n flags[feature] = item?.toLowerCase() === true.toString() ? true : false;\n });\n\n return flags;\n};\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\nimport { useCallback, useContext } from 'react';\r\nimport { CommandManagerService } from '../../services/command/command-manager-service';\r\nimport { DispatchManagerContext } from '../../services/dispatch-manager/DispatchManager';\r\n\r\ninterface Props {\r\n key: string;\r\n}\r\n\r\ninterface ReturnValue {\r\n initializeCommandManagerServiceOnDispatcher: (\r\n key: string,\r\n ...reducers: DispatchManagerReducer[]\r\n ) => void;\r\n // The command manager service object that exists on the dispatcher for this groupId\r\n commandManagerService: CommandManagerService | undefined;\r\n}\r\n\r\n// This is a helper hook that will instantiate a command manager service with a single batch command on the dispatcher.\r\n\r\n// NOTE: This can be used in multiple components to share access to the dispatcher for a command manager\r\n// with a batch command, as long as the groupId is the same.\r\nconst useDispatcherWithCommandManagerService = ({ key }: Props): ReturnValue => {\r\n const { setDispatchData, registerReducers, dispatchData, getDispatchData } = useContext(\r\n DispatchManagerContext,\r\n );\r\n // Get the data for this component from the context state variable\r\n const componentDispatchData =\r\n getDispatchData(dispatchData, key) ?? undefined;\r\n\r\n const initializeCommandManagerServiceOnDispatcher = useCallback(\r\n (groupId: string, ...reducers: DispatchManagerReducer[]): void => {\r\n // Register the reducers\r\n registerReducers(groupId, ...reducers);\r\n\r\n // Set the initial dispatch data\r\n setDispatchData(groupId, new CommandManagerService());\r\n },\r\n // NOTE: These 2 functions do not take any dependencies so this function is stable\r\n [registerReducers, setDispatchData],\r\n );\r\n return {\r\n initializeCommandManagerServiceOnDispatcher,\r\n commandManagerService: componentDispatchData,\r\n };\r\n};\r\nexport default useDispatcherWithCommandManagerService;\r\n","import { clone } from 'lodash';\r\nimport { CommandBatchBase } from '../../../classes/commands/CommandBatchBase';\r\nimport { CommandManagerService } from '../command-manager-service';\r\n\r\n// A factory method to generate a reducer that will initialize a command batch object on a command manager\r\n// with a specific type.\r\n// NOTE: The commandBatchClass must have a paramaterless constructor.\r\nconst generateBatchCommandInitializerReducer = (\r\n commandBatchClass: Ctor,\r\n): DispatchManagerReducer => {\r\n const returnValue: DispatchManagerReducer = (\r\n dispatchData: CommandManagerService,\r\n action: DispatchManagerDispatchAction,\r\n ): CommandManagerService => {\r\n const dispatchDataCommands = dispatchData.getCommands();\r\n\r\n // There should be one batch command in this case\r\n if (dispatchDataCommands.length === 1 && dispatchDataCommands[0] instanceof CommandBatchBase) {\r\n return dispatchData;\r\n }\r\n // Initialize the batch command\r\n const commandManager = clone(dispatchData);\r\n commandManager.addCommand(new commandBatchClass());\r\n\r\n return commandManager;\r\n };\r\n\r\n return returnValue;\r\n};\r\n\r\nexport default generateBatchCommandInitializerReducer;\r\n","import { CommandManagerService } from '../command-manager-service';\r\n\r\nconst commandManagerDispatchReducer: DispatchManagerReducer<\r\n CommandManagerService,\r\n DispatchManagerDispatchActions_CommandManager\r\n> = (\r\n dispatchData: CommandManagerService,\r\n action: DispatchManagerDispatchAction,\r\n): CommandManagerService => {\r\n switch (action.type) {\r\n case 'clear-command-manager':\r\n return dispatchData.clone().clearCommands();\r\n\r\n case 'update-command-manager':\r\n return action.data as CommandManagerService;\r\n\r\n default:\r\n return dispatchData;\r\n }\r\n};\r\n\r\nexport default commandManagerDispatchReducer;\r\n","import { CommandManagerService } from '../services/command/command-manager-service';\n\n// NOTE: This returns a copy of the command manager service after adding a command to a\n// batch command object that exists in the command manager service's commands collection.\n// Optionally takes a the batch command's class to create the batch command if one doesnt exist.\nconst addCommandToBatchCommandObject = (\n commandManagerService: CommandManagerService,\n commandToAdd: ICommand,\n commandBatchClass?: Ctor,\n): CommandManagerService => {\n const clonedCommandManagerService = commandManagerService.clone();\n let batchCommandObject = getBatchCommandObjectFromCommandManager(clonedCommandManagerService);\n\n // were we able to get a batch command?\n // if we couldnt find one, should we create one and add it?\n if (!batchCommandObject && commandBatchClass) {\n batchCommandObject = new commandBatchClass();\n clonedCommandManagerService.addCommand(batchCommandObject!);\n }\n\n if (batchCommandObject) {\n batchCommandObject.addCommand(commandToAdd);\n } else {\n throw new Error('Unable to get the batch command from the given command manager.');\n }\n\n return clonedCommandManagerService;\n};\n\n// Gets the first command from the command manager service\nconst getBatchCommandObjectFromCommandManager = (\n commandManagerService: CommandManagerService,\n): IBatchCommand | undefined => {\n return commandManagerService.getCommands()[0] as IBatchCommand | undefined;\n};\n\nexport { addCommandToBatchCommandObject, getBatchCommandObjectFromCommandManager };\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { useState } from 'react';\r\nimport { Input } from 'reactstrap';\r\nimport './BTSearchBar.scss';\r\n\r\ninterface Props {\r\n onChange: (searchText: string) => void;\r\n 'data-testid'?: string;\r\n}\r\n\r\nconst BTSearchBar: React.FC = (props) => {\r\n const [searchText, setSearchText] = useState('');\r\n\r\n return (\r\n
\r\n
\r\n {\r\n const newSearchText = e.target.value;\r\n setSearchText(newSearchText);\r\n props.onChange(newSearchText);\r\n }}\r\n value={searchText}\r\n data-testid={props['data-testid']}\r\n />\r\n
\r\n \r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default BTSearchBar;\r\n","import { useContext, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useLogger } from '../../../services/logger/Logger';\nimport { NotificationService } from '../../../services/notification/notification-service';\nimport { NotificationPanelContext } from '../../common-page-components/notification-panel/NotificationPanelContext';\n\nconst useDegradedActionNotifications = (componentName?: string): void => {\n const { t } = useTranslation();\n const logger = useLogger();\n const { showErrorNotification, showSuccessNotification, showWarningNotification } = useContext(\n NotificationPanelContext,\n );\n\n // Whenever a command results in degraded performance, show the degraded action warning message\n useEffect(() => {\n NotificationService.onDegradedActionStarted((message) => {\n logger.logDebug(\n `${\n !componentName ? 'useDegradedActionNotifications' : componentName\n }.onDegradedActionStarted`,\n message,\n );\n\n // lets warn that we're in a degraded performance state\n showWarningNotification(t('general:warning'), t('general:degradedActionWarning'));\n });\n\n return function cleanup() {\n NotificationService.offDegradedActionStarted();\n };\n }, [t, logger, showWarningNotification, componentName]);\n\n // Whenever the degraded action finishes, show the appropriate message\n useEffect(() => {\n NotificationService.onDegradedActionFinished((message) => {\n logger.logDebug(\n `${\n !componentName ? 'useDegradedActionNotifications' : componentName\n }.onDegradedActionFinished`,\n message,\n );\n\n if (message.IsSuccess) {\n // NOTE: We wait 4 seconds before refreshing the page to give time for\n // the warning notification to display and be read\n setTimeout(() => {\n window.location.reload();\n }, 4_000);\n } else {\n showErrorNotification(t('general:error'), t('general:degradedActionFailed'));\n }\n });\n\n return function cleanup() {\n NotificationService.offDegradedActionFinished();\n };\n }, [t, logger, showSuccessNotification, showErrorNotification, componentName]);\n};\n\nexport default useDegradedActionNotifications;\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { ReactElement } from 'react';\r\nimport { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';\r\nimport './BTSortableContainer.scss';\r\n\r\nexport interface BTSortableItem {\r\n value: JSX.Element;\r\n key: string;\r\n}\r\n\r\nexport interface BTSortableProps {\r\n items: BTSortableItem[];\r\n onSortEnd: ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => void;\r\n ghostRowCssClass: string;\r\n isSortable: boolean;\r\n isEditable?: boolean;\r\n}\r\n\r\ninterface BTSortableItemProps {\r\n value: JSX.Element;\r\n isSortable: boolean;\r\n isEditable: boolean;\r\n}\r\n\r\ninterface BTSortableListProps {\r\n items: BTSortableItem[];\r\n disabled: boolean;\r\n isEditable: boolean;\r\n isSortable: boolean;\r\n}\r\n\r\nconst DragHandle = SortableHandle(() => (\r\n
\r\n \r\n
\r\n));\r\n\r\nconst SortableItem = SortableElement(({ value, isEditable, isSortable }: BTSortableItemProps) => (\r\n
  • \r\n {isEditable && isSortable ? : <>}\r\n {value}\r\n
  • \r\n));\r\n\r\nconst SortableList = SortableContainer(\r\n ({ items, disabled, isEditable, isSortable }: BTSortableListProps) => {\r\n return (\r\n
      \r\n {items.map((item, index) => (\r\n \r\n ))}\r\n
    \r\n );\r\n },\r\n);\r\n\r\nconst BTSortableContainer: React.FC = (props) => {\r\n const renderBTSortableContainer = (): ReactElement => {\r\n return (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n );\r\n };\r\n return renderBTSortableContainer();\r\n};\r\n\r\nexport default BTSortableContainer;\r\n","const AlternateEntityLimits = {\r\n Name_MaxLength: 4000,\r\n};\r\n\r\nconst AdjustmentEntityLimits = {\r\n Notes_MaxLength: 4000,\r\n};\r\n\r\nconst BidderEntityLimits = {\r\n CompanyName_MaxLength: 200,\r\n PhoneNumber_MaxLength: 30,\r\n FaxNumber_MaxLength: 30,\r\n PrimaryContactName_MaxLength: 200,\r\n PrimaryContactEmail_MaxLength: 200,\r\n Notes_MaxLength: 4000,\r\n};\r\n\r\nconst BidPackageEntityLimits = {\r\n Code_MaxLength: 4000,\r\n Description_MaxLength: 4000,\r\n Notes_MaxLength: 4000,\r\n};\r\n\r\nconst BidPackageLineItemEntityLimits = {\r\n Description_MaxLength: 4000,\r\n Metadata_MaxLength: 4000,\r\n};\r\n\r\nconst FeeEntityLimits = {\r\n Name_MaxLength: 4000,\r\n};\r\n\r\nconst GeneralConditionEntityLimits = {\r\n Code_MaxLength: BidPackageEntityLimits.Code_MaxLength,\r\n Description_MaxLength: BidPackageEntityLimits.Description_MaxLength,\r\n};\r\n\r\nconst ProjectEntityLimits = {\r\n Name_MaxLength: 4000,\r\n Subtitle_MaxLength: 4000,\r\n StreetAddress_MaxLength: 4000,\r\n AptSuiteBldg_MaxLength: 4000,\r\n City_MaxLength: 4000,\r\n StateOrRegion_MaxLength: 4000,\r\n Country_MaxLength: 4000,\r\n PostalCode_MaxLength: 4000,\r\n Architect_MaxLength: 4000,\r\n Owner_MaxLength: 4000,\r\n Notes_MaxLength: 4000,\r\n};\r\n\r\nconst RequirementEntityLimits = {\r\n Description_MaxLength: 840,\r\n};\r\n\r\nconst RequirementFulfillmentEntityLimits = {\r\n Value_MaxLength: 4000,\r\n};\r\n\r\nconst UnitOfMeasureEntityLimits = {\r\n Name_MaxLength: 50,\r\n};\r\n\r\nconst UserEntityLimits = {\r\n Email_MaxLength: 250,\r\n Location_MaxLength: 200,\r\n Roles: 200,\r\n Name: 256,\r\n};\r\n\r\nconst EntityValidationConstants = {\r\n AlternateEntityLimits,\r\n AdjustmentEntityLimits,\r\n BidderEntityLimits,\r\n BidPackageEntityLimits,\r\n BidPackageLineItemEntityLimits,\r\n FeeEntityLimits,\r\n GeneralConditionEntityLimits,\r\n ProjectEntityLimits,\r\n RequirementEntityLimits,\r\n RequirementFulfillmentEntityLimits,\r\n UnitOfMeasureEntityLimits,\r\n UserEntityLimits,\r\n};\r\n\r\nexport default EntityValidationConstants;\r\n","import { Input, InputProps } from '@progress/kendo-react-inputs';\r\nimport React, { useState } from 'react';\r\nimport { generateUuid } from '../../../utils/uuid';\r\n\r\ninterface Props {\r\n textAlignment?: 'left' | 'right';\r\n}\r\n\r\n// A very basic wrapped Kendo input element that we can use independently of Formik\r\nconst BTInput: React.ForwardRefRenderFunction = (\r\n { id, name, label, autoFocus, textAlignment, ...rest },\r\n ref,\r\n) => {\r\n const [inputIdentifier] = useState(id || name || label || generateUuid());\r\n\r\n textAlignment = textAlignment !== undefined ? textAlignment : 'left';\r\n\r\n return (\r\n // Fall back to using the label for the input name\r\n
    \r\n {label ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n {\r\n if (e) {\r\n if (ref) {\r\n (ref as React.MutableRefObject).current = e;\r\n }\r\n\r\n if (inputIdentifier && e.element && !e.element.getAttribute('data-testid')) {\r\n e.element.setAttribute('data-testid', inputIdentifier);\r\n }\r\n }\r\n }}\r\n name={inputIdentifier}\r\n id={inputIdentifier}\r\n autoFocus={autoFocus}\r\n style={{\r\n textAlign: textAlignment,\r\n }}\r\n {...rest}\r\n />\r\n
    \r\n );\r\n};\r\n\r\nexport default React.forwardRef(BTInput);\r\n","import { RadioGroupChangeEvent } from '@progress/kendo-react-inputs';\r\nimport { InputChangeEvent } from '@progress/kendo-react-inputs/dist/npm/input/interfaces/InputChangeEvent';\r\nimport { cloneDeep } from 'lodash';\r\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport GeneralConstants from '../../../../../constants/general';\r\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\r\nimport BTIconButton from '../../../../common-page-components/controls/icon-button/BTIconButton';\r\nimport BTInput from '../../../../common-page-components/inputs/BTInput';\r\nimport { RequirementFulfillmentTypes } from '../../../../enums/bid-package-enums';\r\nimport BTRadioGroup, {\r\n BTRadioGroupOption,\r\n} from './../../../../common-page-components/inputs/BTRadioGroup';\r\nimport './TradeRequirementsListing.scss';\r\n\r\ninterface Props {\r\n errors: RequirementError[];\r\n hasErrors: boolean;\r\n isEditable: boolean;\r\n tradeRequirementDefinition: TradeRequirementDefinitionInterface;\r\n addTradeRequirementDefinition: (\r\n definition: TradeRequirementDefinitionInterface,\r\n ) => TradeRequirementDefinitionInterface[];\r\n updateTradeRequirementDefinition: (\r\n definition: TradeRequirementDefinitionInterface,\r\n updatedDefinition: TradeRequirementDefinitionInterface,\r\n ) => void;\r\n deleteTradeRequirementDefinition: (definition: TradeRequirementDefinitionInterface) => void;\r\n validateTradeRequirementDefinition: (definition: TradeRequirementDefinitionInterface) => boolean;\r\n}\r\n\r\nconst TradeRequirementsListing: React.FC = ({\r\n errors,\r\n hasErrors,\r\n isEditable,\r\n tradeRequirementDefinition,\r\n addTradeRequirementDefinition,\r\n updateTradeRequirementDefinition,\r\n deleteTradeRequirementDefinition,\r\n validateTradeRequirementDefinition,\r\n}) => {\r\n const { t } = useTranslation();\r\n const [definition, setDefinition] = useState(\r\n tradeRequirementDefinition,\r\n );\r\n\r\n // local variable for tracking changes.\r\n const definitionCopy = useRef(tradeRequirementDefinition);\r\n\r\n // local variable for preventing weird overwrites from the useEffect hook.\r\n const isFocused = useRef(false);\r\n\r\n const radioButtonOptions: BTRadioGroupOption[] = [\r\n {\r\n label: t('bid-package-maintenance:contributesToBid'),\r\n value: RequirementFulfillmentTypes.Quantitative,\r\n },\r\n {\r\n label: t('bid-package-maintenance:yesOrNo'),\r\n value: RequirementFulfillmentTypes.Qualitative,\r\n },\r\n {\r\n label: t('general:text'),\r\n value: RequirementFulfillmentTypes.Freeform,\r\n },\r\n ];\r\n\r\n // This is required to get things back in sync when the user discards changes\r\n useEffect(() => {\r\n if (!hasErrors && !definition.isNew && !isFocused.current) {\r\n setDefinition(tradeRequirementDefinition);\r\n }\r\n }, [tradeRequirementDefinition, hasErrors, definition.isNew]);\r\n\r\n const addButtonClick = () => {\r\n if (validateTradeRequirementDefinition(definition)) {\r\n addTradeRequirementDefinition(definition);\r\n }\r\n };\r\n\r\n const deleteButtonClick = () => {\r\n deleteTradeRequirementDefinition(definition);\r\n };\r\n\r\n const descriptionChangeHandler = useCallback(\r\n (event: InputChangeEvent) => {\r\n const updatedDefinition: TradeRequirementDefinitionInterface = {\r\n ...definition,\r\n description: event.target.value?.toString() ?? '',\r\n };\r\n\r\n isFocused.current = true;\r\n\r\n // Set local definition state\r\n setDefinition(updatedDefinition);\r\n // Check that the latest definition is valid\r\n validateTradeRequirementDefinition(updatedDefinition);\r\n },\r\n [definition, validateTradeRequirementDefinition],\r\n );\r\n\r\n const descriptionBlurHandler = useCallback(\r\n (event: React.FocusEvent) => {\r\n const updatedDefinition: TradeRequirementDefinitionInterface = {\r\n ...definition,\r\n description: event.target.value?.toString() ?? '',\r\n };\r\n\r\n isFocused.current = false;\r\n\r\n // check isNew first to short circuit validation (it's already happened in onChange)\r\n if (!definition.isNew && validateTradeRequirementDefinition(updatedDefinition)) {\r\n // Update the parent component\r\n updateTradeRequirementDefinition(definitionCopy.current, updatedDefinition);\r\n // Update the local copy with our most recent \"valid blur\"\r\n definitionCopy.current = cloneDeep(updatedDefinition);\r\n }\r\n },\r\n [definition, updateTradeRequirementDefinition, validateTradeRequirementDefinition],\r\n );\r\n\r\n const requirementFulfillmentTypeChangeHandler = useCallback(\r\n (event: RadioGroupChangeEvent) => {\r\n const updatedDefinition: TradeRequirementDefinitionInterface = {\r\n ...definition,\r\n requirementFulfillmentType: event.value,\r\n };\r\n // Set local definition state\r\n setDefinition(updatedDefinition);\r\n // Check that the latest definition isn't new ('new' records are handled in addButtonClick())\r\n if (!definition.isNew) {\r\n // Update the parent component\r\n updateTradeRequirementDefinition(definition, updatedDefinition);\r\n // Even though we don't validate input on the requirement type, we must update\r\n definitionCopy.current = cloneDeep(updatedDefinition);\r\n }\r\n },\r\n [definition, updateTradeRequirementDefinition],\r\n );\r\n\r\n const resetRow = () => {\r\n setDefinition({ ...tradeRequirementDefinition, description: '' });\r\n };\r\n\r\n return (\r\n
    \r\n
    \r\n {!isEditable ? (\r\n \r\n ) : (\r\n 0)}\r\n maxLength={EntityValidationConstants.RequirementEntityLimits.Description_MaxLength}\r\n onKeyDown={(e) => {\r\n if (e.key === GeneralConstants.KEY_ENTER) {\r\n addButtonClick();\r\n }\r\n }}\r\n />\r\n )}\r\n
    \r\n
    \r\n 0}\r\n />\r\n
    \r\n {isEditable ? (\r\n
    \r\n {definition.isNew ? (\r\n
    \r\n {\r\n addButtonClick();\r\n resetRow();\r\n }}\r\n disabled={hasErrors || definition.description === '' || errors.length > 0}\r\n data-testid={'add-trade-requirement-data-testid'}\r\n />\r\n
    \r\n ) : (\r\n
    \r\n {\r\n deleteButtonClick();\r\n }}\r\n data-testid={'delete-trade-requirement-data-testid'}\r\n disabled={errors.length > 0}\r\n />\r\n
    \r\n )}\r\n
    \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n );\r\n};\r\n\r\nexport default TradeRequirementsListing;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport { isEqual, uniq } from 'lodash';\r\nimport React, { useCallback, useContext, useEffect, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router';\r\nimport { Collapse } from 'reactstrap';\r\nimport { CreateTradeRequirementDefinitionCommand } from '../../../../../classes/commands/bid-package-maintenance/trade-requirement-definitions/create-trade-requirement-definition-command';\r\nimport { DeleteTradeRequirementDefinitionCommand } from '../../../../../classes/commands/bid-package-maintenance/trade-requirement-definitions/delete-trade-requirement-definition-command';\r\nimport { UpdateTradeRequirementDefinitionDescriptionCommand } from '../../../../../classes/commands/bid-package-maintenance/trade-requirement-definitions/update-trade-requirement-definition-description-command';\r\nimport { UpdateTradeRequirementDefinitionIndexCommand } from '../../../../../classes/commands/bid-package-maintenance/trade-requirement-definitions/update-trade-requirement-definition-index-command';\r\nimport { UpdateTradeRequirementDefinitionRequirementFulfillmentTypeCommand } from '../../../../../classes/commands/bid-package-maintenance/trade-requirement-definitions/update-trade-requirement-definition-requirement-fulfillment-type-command';\r\nimport ApplicationRoutes from '../../../../../constants/routes';\r\nimport { DispatchManagerContext } from '../../../../../services/dispatch-manager/DispatchManager';\r\nimport { useLogger } from '../../../../../services/logger/Logger';\r\nimport { generateUuid } from '../../../../../utils/uuid';\r\nimport { ConfirmationOverlayContext } from '../../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\r\nimport BTIconButton from '../../../../common-page-components/controls/icon-button/BTIconButton';\r\nimport { LoadingPageOverlayContext } from '../../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport BTSortableContainer, {\r\n BTSortableItem,\r\n} from '../../../../common-page-components/sortable/BTSortableContainer';\r\nimport { RequirementFulfillmentTypes } from '../../../../enums/bid-package-enums';\r\nimport './BidPackageDefinitionListing.scss';\r\nimport TradeRequirementsListing from './TradeRequirementsListing';\r\nimport EntityValidationConstants from './../../../../../constants/general/entity-validation-constants';\r\n\r\ninterface Props {\r\n bidPackageDefinition: BidPackageDefinition;\r\n isReadOnly: boolean;\r\n groupId: string;\r\n tradeRequirementsAreEditable: boolean;\r\n executeBatchCommands: () => void;\r\n editBidPackageDefinitionButtonClick: (bidPackageDefinition: BidPackageDefinition) => void;\r\n deleteBidPackageDefinitionButtonClick: (bidPackageDefinition: BidPackageDefinition) => void;\r\n onEditTradeRequirementsCallback: (bidPackageDefinition: BidPackageDefinition) => void;\r\n onSaveCallback: () => void;\r\n onDiscardCallback: () => void;\r\n}\r\n\r\nconst BidPackageDefinitionListing: React.FC = ({\r\n bidPackageDefinition,\r\n isReadOnly,\r\n groupId,\r\n tradeRequirementsAreEditable,\r\n executeBatchCommands,\r\n editBidPackageDefinitionButtonClick,\r\n deleteBidPackageDefinitionButtonClick,\r\n onEditTradeRequirementsCallback,\r\n onSaveCallback,\r\n onDiscardCallback,\r\n}) => {\r\n const { t } = useTranslation();\r\n const logger = useLogger();\r\n const history = useHistory();\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n const { showErrorNotification, showInfoNotification, showSuccessNotification } = useContext(\r\n NotificationPanelContext,\r\n );\r\n const { dispatchAction } = useContext(DispatchManagerContext);\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [errors, setErrors] = useState([]);\r\n const [isEditable, setIsEditable] = useState(false);\r\n const [bidPackageDefinitionToEdit, setBidPackageDefinitionToEdit] = useState<\r\n BidPackageDefinition\r\n >(bidPackageDefinition);\r\n\r\n const duplicateDescriptionError = t('bid-package-maintenance:duplicateDescriptionError');\r\n const emptyDescriptionError = t('bid-package-maintenance:emptyDescriptionError');\r\n\r\n const generateNewTradeRequirementDefinition = useCallback((): TradeRequirementDefinitionInterface => {\r\n return {\r\n id: generateUuid(),\r\n index: -1,\r\n description: '',\r\n requirementFulfillmentType: RequirementFulfillmentTypes.Qualitative,\r\n isNew: true,\r\n };\r\n }, []);\r\n\r\n const [newTradeRequirementDefinition, setNewTradeRequirementDefinition] = useState<\r\n TradeRequirementDefinitionInterface\r\n >();\r\n\r\n useEffect(() => {\r\n setNewTradeRequirementDefinition(generateNewTradeRequirementDefinition());\r\n }, [generateNewTradeRequirementDefinition]);\r\n\r\n const onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {\r\n if (bidPackageDefinitionToEdit.tradeRequirementDefinitions) {\r\n const updatedDefinitions = [...bidPackageDefinitionToEdit.tradeRequirementDefinitions];\r\n const previousDefinition = bidPackageDefinitionToEdit.tradeRequirementDefinitions[oldIndex];\r\n\r\n if (oldIndex < 0) {\r\n oldIndex += updatedDefinitions.length;\r\n }\r\n if (newIndex < 0) {\r\n newIndex += updatedDefinitions.length;\r\n }\r\n updatedDefinitions.splice(newIndex, 0, updatedDefinitions.splice(oldIndex, 1)[0]);\r\n const updatedDefinition: BidPackageDefinition = {\r\n ...bidPackageDefinitionToEdit,\r\n tradeRequirementDefinitions: updatedDefinitions || [],\r\n };\r\n\r\n dispatchAction(groupId, {\r\n data: new UpdateTradeRequirementDefinitionIndexCommand(\r\n bidPackageDefinition.code,\r\n previousDefinition.description,\r\n newIndex,\r\n ),\r\n type: 'update-trade-requirement-definition-index',\r\n });\r\n setBidPackageDefinitionToEdit(updatedDefinition);\r\n }\r\n };\r\n\r\n const onSubmit = useCallback(async () => {\r\n try {\r\n if (isEqual(bidPackageDefinition, bidPackageDefinitionToEdit)) {\r\n dispatchAction(groupId, {\r\n data: null,\r\n type: 'clear-command-manager',\r\n });\r\n\r\n showInfoNotification(\r\n t('general:noChanges'),\r\n t('bid-package-maintenance:tradeRequirementDefinitionsNoChanges'),\r\n );\r\n } else {\r\n showPageLoadingOverlay();\r\n await executeBatchCommands();\r\n showSuccessNotification(\r\n t('general:success'),\r\n t('bid-package-maintenance:updateTradeRequirementDefinitionsSuccess'),\r\n );\r\n }\r\n\r\n setIsEditable(false);\r\n onSaveCallback();\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(\r\n t('general:error'),\r\n t('bid-package-maintenance:updateTradeRequirementDefinitionsError'),\r\n );\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n }, [\r\n bidPackageDefinition,\r\n bidPackageDefinitionToEdit,\r\n onSaveCallback,\r\n dispatchAction,\r\n groupId,\r\n showInfoNotification,\r\n t,\r\n showPageLoadingOverlay,\r\n executeBatchCommands,\r\n showSuccessNotification,\r\n logger,\r\n showErrorNotification,\r\n history,\r\n hidePageLoadingOverlay,\r\n ]);\r\n\r\n const discardChanges = useCallback(() => {\r\n dispatchAction(groupId, {\r\n data: null,\r\n type: 'clear-command-manager',\r\n });\r\n setBidPackageDefinitionToEdit(bidPackageDefinition);\r\n setErrors([]);\r\n setIsEditable(false);\r\n onDiscardCallback();\r\n }, [dispatchAction, groupId, bidPackageDefinition, onDiscardCallback]);\r\n\r\n const onDiscard = useCallback(() => {\r\n if (!isEqual(bidPackageDefinitionToEdit, bidPackageDefinition) || errors.length > 0) {\r\n showConfirmationOverlay({\r\n text: t('general:discardConfirmation'),\r\n buttons: [\r\n {\r\n text: t('general:discard'),\r\n onClick: (): void => {\r\n discardChanges();\r\n hideConfirmationOverlay();\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:cancel'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n } else {\r\n setIsEditable(false);\r\n onDiscardCallback();\r\n }\r\n }, [\r\n bidPackageDefinitionToEdit,\r\n discardChanges,\r\n errors.length,\r\n hideConfirmationOverlay,\r\n bidPackageDefinition,\r\n showConfirmationOverlay,\r\n t,\r\n onDiscardCallback,\r\n ]);\r\n\r\n const setTradeRequirementErrors = useCallback(\r\n (id: string, errorMessages: string[]): RequirementError[] => {\r\n // Remove old errors'\r\n const updatedErrors = errors.filter((u) => u.id !== id);\r\n\r\n // Add new errors\r\n errorMessages.map((e) => {\r\n return updatedErrors.push({\r\n id: id,\r\n message: e,\r\n });\r\n });\r\n\r\n setErrors(updatedErrors);\r\n return updatedErrors;\r\n },\r\n [errors],\r\n );\r\n\r\n const validateTradeRequirementDefinition = useCallback(\r\n (definition: TradeRequirementDefinitionInterface): boolean => {\r\n const errorMessages: string[] = [];\r\n const description = definition.description ? definition.description.trim().toLowerCase() : '';\r\n\r\n // Check if the description is empty or whitespace\r\n if (!(description || '').length) {\r\n errorMessages.push(emptyDescriptionError);\r\n }\r\n\r\n // Check if the description is longer than the max length\r\n if (\r\n description.length > EntityValidationConstants.RequirementEntityLimits.Description_MaxLength\r\n ) {\r\n errorMessages.push(\r\n t('bid-package-maintenance:requirementDescriptionMaxLength', {\r\n maxLength: EntityValidationConstants.RequirementEntityLimits.Description_MaxLength,\r\n }),\r\n );\r\n }\r\n\r\n // Map the descriptions, trimmed and converted to lower case to account for whitespace and different casings\r\n const descriptions = bidPackageDefinitionToEdit.tradeRequirementDefinitions\r\n ? bidPackageDefinitionToEdit.tradeRequirementDefinitions.map((t) =>\r\n t.description ? t.description.trim().toLowerCase() : '',\r\n )\r\n : [];\r\n\r\n // Filter the modified descriptions to only look at values that appear more than once\r\n if (definition.isNew) {\r\n if (descriptions.indexOf(description) !== -1) {\r\n errorMessages.push(duplicateDescriptionError);\r\n }\r\n } else {\r\n let duplicateDescriptions = [];\r\n duplicateDescriptions = descriptions.filter(\r\n (item, index) => item === description && index !== definition.index,\r\n );\r\n\r\n if (duplicateDescriptions.length > 0) {\r\n errorMessages.push(duplicateDescriptionError);\r\n }\r\n }\r\n\r\n // Update errors in parent component and set flag to trigger error styles\r\n setTradeRequirementErrors(definition.id, errorMessages);\r\n if (errorMessages.length > 0) {\r\n return false;\r\n }\r\n return true;\r\n },\r\n [\r\n bidPackageDefinitionToEdit.tradeRequirementDefinitions,\r\n duplicateDescriptionError,\r\n emptyDescriptionError,\r\n setTradeRequirementErrors,\r\n t,\r\n ],\r\n );\r\n\r\n const addTradeRequirementDefinition = useCallback(\r\n (\r\n tradeRequirement: TradeRequirementDefinitionInterface,\r\n ): TradeRequirementDefinitionInterface[] => {\r\n let updatedTradeRequirements: TradeRequirementDefinitionInterface[] = [];\r\n\r\n try {\r\n tradeRequirement.index =\r\n bidPackageDefinitionToEdit.tradeRequirementDefinitions?.length || 0;\r\n tradeRequirement.isNew = false;\r\n updatedTradeRequirements = bidPackageDefinitionToEdit.tradeRequirementDefinitions\r\n ? [...bidPackageDefinitionToEdit.tradeRequirementDefinitions, tradeRequirement]\r\n : [tradeRequirement];\r\n setBidPackageDefinitionToEdit({\r\n ...bidPackageDefinitionToEdit,\r\n tradeRequirementDefinitions: updatedTradeRequirements,\r\n });\r\n setNewTradeRequirementDefinition(generateNewTradeRequirementDefinition());\r\n } catch (error) {\r\n logger.logError(error);\r\n\r\n showErrorNotification(\r\n t('general:error'),\r\n t('bid-package-maintenance:createTradeRequirementDefinitionsError'),\r\n );\r\n\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n }\r\n\r\n dispatchAction(groupId, {\r\n data: new CreateTradeRequirementDefinitionCommand(\r\n bidPackageDefinition.code,\r\n tradeRequirement.index,\r\n tradeRequirement.description.trim(),\r\n tradeRequirement.requirementFulfillmentType,\r\n ),\r\n type: 'create-trade-requirement-definition',\r\n });\r\n\r\n return updatedTradeRequirements;\r\n },\r\n [\r\n bidPackageDefinition.code,\r\n bidPackageDefinitionToEdit,\r\n dispatchAction,\r\n generateNewTradeRequirementDefinition,\r\n groupId,\r\n showErrorNotification,\r\n t,\r\n logger,\r\n history,\r\n ],\r\n );\r\n\r\n const updateTradeRequirementDefinition = useCallback(\r\n (\r\n definition: TradeRequirementDefinitionInterface,\r\n updatedDefinition: TradeRequirementDefinitionInterface,\r\n ): void => {\r\n let updatedTradeRequirements: TradeRequirementDefinitionInterface[] = [];\r\n if (bidPackageDefinitionToEdit.tradeRequirementDefinitions) {\r\n updatedTradeRequirements = [...bidPackageDefinitionToEdit.tradeRequirementDefinitions];\r\n }\r\n\r\n try {\r\n const index = bidPackageDefinitionToEdit.tradeRequirementDefinitions?.findIndex(\r\n (t) => t.id === definition.id,\r\n );\r\n\r\n if (index !== undefined && index > -1) {\r\n updatedTradeRequirements.splice(index, 1, updatedDefinition);\r\n setBidPackageDefinitionToEdit({\r\n ...bidPackageDefinitionToEdit,\r\n tradeRequirementDefinitions: updatedTradeRequirements,\r\n });\r\n }\r\n\r\n if (definition.description !== updatedDefinition.description) {\r\n dispatchAction(groupId, {\r\n data: new UpdateTradeRequirementDefinitionDescriptionCommand(\r\n bidPackageDefinition.code,\r\n definition.description,\r\n updatedDefinition.description.trim(),\r\n ),\r\n type: 'update-trade-requirement-definition-description',\r\n });\r\n }\r\n\r\n if (\r\n definition.requirementFulfillmentType !== updatedDefinition.requirementFulfillmentType\r\n ) {\r\n dispatchAction(groupId, {\r\n data: new UpdateTradeRequirementDefinitionRequirementFulfillmentTypeCommand(\r\n bidPackageDefinition.code,\r\n definition.description,\r\n updatedDefinition.requirementFulfillmentType,\r\n ),\r\n type: 'update-trade-requirement-definition-requirement-fulfillment-type',\r\n });\r\n }\r\n } catch (error) {\r\n logger.logError(error);\r\n\r\n showErrorNotification(\r\n t('general:error'),\r\n t('bid-package-maintenance:updateTradeRequirementDefinitionError'),\r\n );\r\n\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n }\r\n },\r\n [\r\n bidPackageDefinition.code,\r\n bidPackageDefinitionToEdit,\r\n dispatchAction,\r\n groupId,\r\n showErrorNotification,\r\n t,\r\n logger,\r\n history,\r\n ],\r\n );\r\n\r\n const deleteTradeRequirementDefinition = useCallback(\r\n (tradeRequirement: TradeRequirementDefinitionInterface): void => {\r\n let updatedTradeRequirements: TradeRequirementDefinitionInterface[] = [];\r\n if (bidPackageDefinitionToEdit.tradeRequirementDefinitions) {\r\n updatedTradeRequirements = [...bidPackageDefinitionToEdit.tradeRequirementDefinitions];\r\n }\r\n showConfirmationOverlay({\r\n text: t('bid-package-maintenance:confirmDeleteTradeRequirementDefinition', {\r\n description: tradeRequirement.description,\r\n }),\r\n buttons: [\r\n {\r\n text: t('general:yes'),\r\n onClick: (): void => {\r\n //Filter out the deleted definition\r\n updatedTradeRequirements =\r\n bidPackageDefinitionToEdit.tradeRequirementDefinitions?.filter(\r\n (t) => t.description !== tradeRequirement.description,\r\n ) || [];\r\n\r\n //Reset the index property based on the new collection\r\n updatedTradeRequirements.map((t, idx) => {\r\n return (t.index = idx);\r\n });\r\n\r\n setBidPackageDefinitionToEdit({\r\n ...bidPackageDefinitionToEdit,\r\n tradeRequirementDefinitions: updatedTradeRequirements,\r\n });\r\n\r\n const updatedErrors = errors.filter((e) => e.id !== tradeRequirement.id);\r\n setErrors(updatedErrors);\r\n\r\n dispatchAction(groupId, {\r\n data: new DeleteTradeRequirementDefinitionCommand(\r\n bidPackageDefinition.code,\r\n tradeRequirement.description,\r\n ),\r\n type: 'delete-trade-requirement-definition',\r\n });\r\n\r\n hideConfirmationOverlay();\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:no'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n },\r\n [\r\n bidPackageDefinition.code,\r\n bidPackageDefinitionToEdit,\r\n dispatchAction,\r\n errors,\r\n groupId,\r\n hideConfirmationOverlay,\r\n showConfirmationOverlay,\r\n t,\r\n ],\r\n );\r\n\r\n const editTradeRequirementDefinitionsButtonClick = () => {\r\n if (!isEditable) {\r\n setIsOpen(true);\r\n setIsEditable(true);\r\n onEditTradeRequirementsCallback(bidPackageDefinition);\r\n }\r\n };\r\n\r\n const definitionHasErrors = useCallback(\r\n (id: string): boolean => {\r\n return errors.find((e) => e.id === id) !== undefined;\r\n },\r\n [errors],\r\n );\r\n\r\n const renderTradeRequirementListings = useCallback((): BTSortableItem[] => {\r\n const generatedTradeRequirementListings = bidPackageDefinitionToEdit.tradeRequirementDefinitions\r\n ? bidPackageDefinitionToEdit.tradeRequirementDefinitions.map((definition) => {\r\n const item: BTSortableItem = {\r\n value: (\r\n \r\n ),\r\n key: definition.id,\r\n };\r\n return item;\r\n })\r\n : [];\r\n return generatedTradeRequirementListings;\r\n }, [\r\n addTradeRequirementDefinition,\r\n bidPackageDefinitionToEdit.tradeRequirementDefinitions,\r\n definitionHasErrors,\r\n deleteTradeRequirementDefinition,\r\n errors,\r\n isReadOnly,\r\n isEditable,\r\n updateTradeRequirementDefinition,\r\n validateTradeRequirementDefinition,\r\n ]);\r\n\r\n return (\r\n <>\r\n
    \r\n
    \r\n
    \r\n {\r\n setIsOpen(!isOpen);\r\n }}\r\n >\r\n

    \r\n \r\n \r\n \r\n {`${bidPackageDefinition.code} - ${bidPackageDefinition.description}`}\r\n

    \r\n \r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n {\r\n editBidPackageDefinitionButtonClick(bidPackageDefinition);\r\n }}\r\n data-testid={'edit-bid-package-data-testid'}\r\n disabled={isReadOnly}\r\n />\r\n \r\n {\r\n deleteBidPackageDefinitionButtonClick(bidPackageDefinition);\r\n }}\r\n data-testid={'delete-bid-package-data-testid'}\r\n disabled={isReadOnly}\r\n />\r\n
    \r\n
    \r\n
    \r\n\r\n \r\n {bidPackageDefinitionToEdit.tradeRequirementDefinitions &&\r\n bidPackageDefinitionToEdit.tradeRequirementDefinitions.length === 0 &&\r\n !isEditable ? (\r\n

    \r\n {t('bid-package-maintenance:noTradeRequirementDefinitions')}\r\n

    \r\n ) : (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n )}\r\n \r\n {!isReadOnly && isEditable && newTradeRequirementDefinition && (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n 0}\r\n data-testid={'save-trade-requirement-definition-changes-data-testid'}\r\n />\r\n \r\n
    \r\n
    0 ? 'errorArea' : 'errorArea hidden'}>\r\n {errors &&\r\n uniq(errors.map((error: RequirementError) => error.message)).map(\r\n (errorMessage) => {\r\n return (\r\n \r\n );\r\n },\r\n )}\r\n
    \r\n
    \r\n
    \r\n )}\r\n
    \r\n \r\n );\r\n};\r\n\r\nexport default BidPackageDefinitionListing;\r\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport BidPackageDefinitionListing from './BidPackageDefinitionListing';\n\ninterface Props {\n bidPackageDefinitions: BidPackageDefinition[];\n isReadOnly: boolean;\n bidPackageDefinitionDispatchKey: string;\n executeBatchCommandCallback: () => void;\n editBidPackageDefinitionButtonClick: (bidPackageDefinition: BidPackageDefinition) => void;\n deleteBidPackageDefinitionButtonClick: (bidPackageDefinition: BidPackageDefinition) => void;\n}\n\nconst BidPackageDefinitionListingContainer: React.FC = (props) => {\n const { t } = useTranslation();\n\n const [\n bidPackageIdOfTradeRequirementsBeingEdited,\n setBidPackageIdOfTradeRequirementsBeingEdited,\n ] = useState();\n\n return (\n
    \n {props.bidPackageDefinitions.length > 0 ? (\n props.bidPackageDefinitions.map((bidPackageDefinition, i) => {\n return (\n \n {i > 0 ?
    : <>}\n\n {\n setBidPackageIdOfTradeRequirementsBeingEdited(bidPackageDefinition.id);\n }}\n onSaveCallback={() => {\n setBidPackageIdOfTradeRequirementsBeingEdited(undefined);\n }}\n onDiscardCallback={() => {\n setBidPackageIdOfTradeRequirementsBeingEdited(undefined);\n }}\n />\n
    \n );\n })\n ) : (\n
    \n {t('bid-package-maintenance:bidPackagesNotFound')}\n
    \n )}\n
    \n );\n};\n\nexport default BidPackageDefinitionListingContainer;\n","import { FormikErrors } from 'formik';\r\n\r\n// NOTE: using `any` here because of metaprogramming\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nconst getFormErrorMessages = (errors: FormikErrors): string[] => {\r\n const errorMessages: string[] = [];\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const getStringValues = (values: any[]): string[] => {\r\n const stringValues: string[] = [];\r\n\r\n values.forEach((val) => {\r\n if (typeof val === 'string') {\r\n stringValues.push(val);\r\n return;\r\n }\r\n\r\n if (Array.isArray(val)) {\r\n stringValues.push(...getStringValues(val));\r\n return;\r\n }\r\n\r\n if (typeof val === 'object') {\r\n stringValues.push(...getStringValues(Object.values(val)));\r\n return;\r\n }\r\n });\r\n\r\n return stringValues;\r\n };\r\n\r\n const stringValues = getStringValues(Object.values(errors));\r\n errorMessages.push(...stringValues);\r\n\r\n return errorMessages;\r\n};\r\n\r\nexport { getFormErrorMessages };\r\n","import React from 'react';\nimport './FormErrorContainer.scss';\nimport { sortBy } from 'lodash';\n\ninterface Props {\n errorMessages: string[];\n}\n\nconst FormErrorContainer: React.FC = (props) => {\n const containerCssClass = props.errorMessages && props.errorMessages.length ? 'isDisplayed' : '';\n const uniqueErrorMessages = sortBy(Array.from(new Set(props.errorMessages)), (v) => v);\n\n return (\n
    \n
    \n {uniqueErrorMessages.map((currErrorMessage, i) => {\n return (\n
    \n {currErrorMessage}\n
    \n );\n })}\n
    \n
    \n );\n};\n\nexport default FormErrorContainer;\n","import { useEffect } from 'react';\r\n\r\ninterface Props {\r\n autoFocus: boolean;\r\n inputRef: React.MutableRefObject;\r\n}\r\n\r\n// In order to avoid having a conditional hook, we pass in the autoFocus property and allow the hook to determine if it needs to focus the input\r\nconst useFocusOnRender = ({ autoFocus, inputRef }: Props): void => {\r\n useEffect(() => {\r\n const input = inputRef.current as HTMLInputElement;\r\n if (autoFocus && input) {\r\n // This timeout is needed to allow all renders to complete before calling focus\r\n setTimeout(() => {\r\n input.focus();\r\n }, 50);\r\n }\r\n }, [autoFocus, inputRef]);\r\n};\r\n\r\nexport default useFocusOnRender;\r\n","import React, { useRef } from 'react';\r\nimport { Input } from '@progress/kendo-react-inputs';\r\nimport { Field, FieldProps } from 'formik';\r\nimport { get } from 'lodash';\r\nimport useFocusOnRender from './hooks/useFocusOnRender';\r\nimport './Forms.scss';\r\n\r\ninterface Props {\r\n label: string;\r\n name: string;\r\n onBlur?: (event: React.FocusEvent) => void;\r\n validator?: (value: string) => string | void;\r\n disabled?: boolean;\r\n tabIndex?: number;\r\n tooltip?: string;\r\n autoFocus?: boolean;\r\n 'data-testid'?: string;\r\n maxLength?: number;\r\n}\r\n\r\nconst WrappedInput: React.FC = ({\r\n autoFocus,\r\n field,\r\n form,\r\n label,\r\n onBlur,\r\n maxLength,\r\n ...rest\r\n}) => {\r\n const errors = get(form.errors, field.name);\r\n const hasErrors = !!errors;\r\n const hasBeenTouched = !!get(form.touched, field.name);\r\n\r\n const classNames = ['formInput'];\r\n\r\n // we only want to show the errors if the editor has been touched or the form has a submit count greater than 0\r\n if (hasErrors && (hasBeenTouched || form.submitCount)) {\r\n classNames.push('formInputError');\r\n }\r\n\r\n const inputRef = useRef(null);\r\n useFocusOnRender({ autoFocus: autoFocus || false, inputRef: inputRef });\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst FormTextInput: React.FC = ({ name, label, validator, tabIndex, tooltip, ...rest }) => {\r\n return (\r\n // TODO: move tooltip to the Kendo Input in WrappedInput\r\n // Kendo's Input isn't properly displaying a tooltip, but it looks fixed in newer versions\r\n
    \r\n \r\n
    \r\n );\r\n};\r\n\r\nexport default FormTextInput;\r\n","import { Form, Formik } from 'formik';\r\nimport React, { useContext, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport * as Yup from 'yup';\r\nimport { UpdateBidPackageDefinitionCodeCommand } from '../../../../../classes/commands/bid-package-maintenance/bid-package-definitions/update-bid-package-definition-code-command';\r\nimport { UpdateBidPackageDefinitionDescriptionCommand } from '../../../../../classes/commands/bid-package-maintenance/bid-package-definitions/update-bid-package-definition-description-command';\r\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\r\nimport { DispatchManagerContext } from '../../../../../services/dispatch-manager/DispatchManager';\r\nimport { getFormErrorMessages } from '../../../../../utils/forms';\r\nimport { areTrimmedStringsEqual } from '../../../../../utils/strings';\r\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\r\nimport FormErrorContainer from '../../../../common-page-components/forms/form-error-container/FormErrorContainer';\r\nimport FormFooter from '../../../../common-page-components/forms/FormFooter';\r\nimport FormTextInput from './../../../../common-page-components/forms/FormTextInput';\r\n\r\ninterface Props {\r\n bidPackageDefinition: BidPackageDefinition;\r\n bidPackageDefinitions: BidPackageDefinition[];\r\n groupId: string;\r\n onSubmitClick: (bidPackageDefinition: BidPackageDefinition) => void;\r\n onDiscardClick: (bidPackageDefinition: BidPackageDefinition) => void;\r\n}\r\n\r\nconst BidPackageEditForm: React.FC = ({\r\n bidPackageDefinition,\r\n bidPackageDefinitions,\r\n groupId,\r\n onSubmitClick,\r\n onDiscardClick,\r\n}) => {\r\n const { t } = useTranslation();\r\n\r\n const FormSchema = Yup.object().shape({\r\n id: Yup.string(),\r\n code: Yup.string()\r\n .trim()\r\n .max(\r\n EntityValidationConstants.BidPackageEntityLimits.Code_MaxLength,\r\n t('bid-package-maintenance:codeMaxLength', {\r\n maxLength: EntityValidationConstants.BidPackageEntityLimits.Code_MaxLength,\r\n }),\r\n )\r\n .required('Bid Package code is a required field'),\r\n description: Yup.string()\r\n .trim()\r\n .max(\r\n EntityValidationConstants.BidPackageEntityLimits.Description_MaxLength,\r\n t('bid-package-maintenance:descriptionMaxLength', {\r\n maxLength: EntityValidationConstants.BidPackageEntityLimits.Description_MaxLength,\r\n }),\r\n )\r\n .required('Bid Package description is a required field'),\r\n isNew: Yup.boolean(),\r\n });\r\n\r\n const { dispatchAction } = useContext(DispatchManagerContext);\r\n const [previousValidCode, setPreviousValidCode] = useState(bidPackageDefinition.code);\r\n\r\n const codeValidator = (bidPackageCode: string): string | void => {\r\n if (areTrimmedStringsEqual(bidPackageDefinition.code, bidPackageCode)) {\r\n return;\r\n }\r\n\r\n if (bidPackageDefinitions.find((b) => areTrimmedStringsEqual(b.code, bidPackageCode))) {\r\n return 'The Bid Package code must be unique';\r\n }\r\n };\r\n\r\n const handleCodeBlur = (bidPackageCode: string): void => {\r\n if (\r\n !bidPackageDefinition.isNew &&\r\n !bidPackageDefinitions.find((b) => b.code.trim() === bidPackageCode)\r\n ) {\r\n dispatchAction(groupId, {\r\n data: new UpdateBidPackageDefinitionCodeCommand(previousValidCode, bidPackageCode.trim()),\r\n type: 'update-bid-package-definition-code',\r\n });\r\n setPreviousValidCode(bidPackageCode);\r\n }\r\n };\r\n\r\n const handleDescriptionBlur = (description: string): void => {\r\n if (!bidPackageDefinition.isNew) {\r\n dispatchAction(groupId, {\r\n data: new UpdateBidPackageDefinitionDescriptionCommand(\r\n previousValidCode,\r\n bidPackageDefinition.description,\r\n description.trim(),\r\n ),\r\n type: 'update-bid-package-definition-description',\r\n });\r\n }\r\n };\r\n\r\n // NOTE: With Formik, once we set the 'initialValues' property, updating it will not update the form values unless we set the 'enableReinitialize' flag\r\n // so we do not even render the Formik element unless the object we bind to its initial values is defined\r\n return (\r\n
    \r\n

    \r\n {`${\r\n bidPackageDefinition && bidPackageDefinition.isNew\r\n ? t('bid-package-maintenance:createBidPackage')\r\n : t('bid-package-maintenance:editBidPackage')\r\n }`}\r\n

    \r\n\r\n {bidPackageDefinition && (\r\n \r\n {({ errors, values, submitCount }): JSX.Element => (\r\n
    \r\n {\r\n
    \r\n
    \r\n ) => {\r\n handleCodeBlur(values.code);\r\n }}\r\n autoFocus={true}\r\n data-testid={'set-bid-package-code-data-testid'}\r\n maxLength={EntityValidationConstants.BidPackageEntityLimits.Code_MaxLength}\r\n />\r\n
    \r\n
    \r\n ) => {\r\n handleDescriptionBlur(values.description);\r\n }}\r\n data-testid={'set-bid-package-description-data-testid'}\r\n maxLength={\r\n EntityValidationConstants.BidPackageEntityLimits.Description_MaxLength\r\n }\r\n />\r\n
    \r\n
    \r\n }\r\n\r\n \r\n
    \r\n \r\n {\r\n onDiscardClick(values);\r\n }}\r\n data-testid={'discard-bid-package-definition-changes-data-testid'}\r\n />\r\n
    \r\n {submitCount > 0 && (\r\n \r\n )}\r\n
    \r\n
    \r\n )}\r\n \r\n )}\r\n
    \r\n );\r\n};\r\n\r\nexport default BidPackageEditForm;\r\n","import { CommandManagerService } from '../../../../../services/command/command-manager-service';\r\nimport { addCommandToBatchCommandObject } from '../../../../../utils/command-manager-service';\r\n\r\nconst bidPackageMaintenanceReducer: DispatchManagerReducer<\r\n CommandManagerService,\r\n DispatchManagerDispatchActions_BidPackageMaintenance\r\n> = (\r\n dispatchData: CommandManagerService,\r\n action: DispatchManagerDispatchAction,\r\n): CommandManagerService => {\r\n switch (action.type) {\r\n case 'create-bid-package-definition':\r\n case 'create-trade-requirement-definition':\r\n case 'delete-bid-package-definition':\r\n case 'delete-trade-requirement-definition':\r\n case 'update-bid-package-definition-code':\r\n case 'update-bid-package-definition-description':\r\n case 'update-trade-requirement-definition-description':\r\n case 'update-trade-requirement-definition-index':\r\n case 'update-trade-requirement-definition-requirement-fulfillment-type':\r\n return addCommandToBatchCommandObject(dispatchData, action.data as ICommand);\r\n\r\n default:\r\n return dispatchData;\r\n }\r\n};\r\n\r\nexport default bidPackageMaintenanceReducer;\r\n","import { isEqual, sortBy } from 'lodash';\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory } from 'react-router';\nimport { Collapse } from 'reactstrap';\nimport { BidPackageMaintenanceBatchCommand } from '../../../../classes/commands/bid-package-maintenance/batch-commands/bid-package-maintenance-batch-commands';\nimport { CreateBidPackageDefinitionCommand } from '../../../../classes/commands/bid-package-maintenance/bid-package-definitions/create-bid-package-definition-command';\nimport { DeleteBidPackageDefinitionCommand } from '../../../../classes/commands/bid-package-maintenance/bid-package-definitions/delete-bid-package-definition-command';\nimport GeneralConstants from '../../../../constants/general';\nimport ApplicationRoutes from '../../../../constants/routes';\nimport useCommandManagerDispatcher from '../../../../hooks/dispatch-manager-helper/useDispatcherWithCommandManagerService';\nimport { BidPackageMaintenanceApi, FrozenEntitiesApi } from '../../../../services';\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\nimport { CommandManagerService } from '../../../../services/command/command-manager-service';\nimport generateBatchCommandInitializerReducer from '../../../../services/command/reducers/command-manager-batch-command-initializer-reducer';\nimport commandManagerDispatchReducer from '../../../../services/command/reducers/command-manager-dispatch-reducer';\nimport { DispatchManagerContext } from '../../../../services/dispatch-manager/DispatchManager';\nimport { useLogger } from '../../../../services/logger/Logger';\nimport '../../../../styles/bt-search-bar.scss';\nimport { addCommandToBatchCommandObject } from '../../../../utils/command-manager-service';\nimport { scrollToRef } from '../../../../utils/general';\nimport { doesStringExistInOtherString, isEmptyOrWhitespace } from '../../../../utils/strings';\nimport { generateUuid } from '../../../../utils/uuid';\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport BTFloatingIconButton from '../../../common-page-components/controls/floating-icon-button/BTFloatingIconButton';\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\nimport BTSearchBar from '../../../common-page-components/search/BTSearchBar';\nimport useDegradedActionNotifications from '../../../shared-page-components/hooks/useDegradedActionNotifications';\nimport './BidPackageMaintenancePage.scss';\nimport BidPackageDefinitionListingContainer from './components/BidPackageDefinitionListingContainer';\nimport BidPackageEditForm from './components/BidPackageEditForm';\nimport bidPackageMaintenanceReducer from './reducers/bid-package-maintenance-reducer';\n\nconst bidPackageDefinitionDispatchKey = 'Bid-Package-Definition-Group-Id';\n\nconst BidPackageMaintenancePage: React.FC = () => {\n const { t } = useTranslation();\n const logger = useLogger();\n const history = useHistory();\n\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n const { dispatchAction } = useContext(DispatchManagerContext);\n const { showSuccessNotification, showInfoNotification, showErrorNotification } = useContext(\n NotificationPanelContext,\n );\n const [isEditAreaOpen, setIsEditAreaOpen] = useState(false);\n const [bidPackageDefinitions, setBidPackageDefinitions] = useState([]);\n const [\n bidPackageDefinitionToEdit,\n setBidPackageDefinitionToEdit,\n ] = useState();\n const bidPackageMaintenancePageEditAreaRef = useRef(null);\n const [searchText, setSearchText] = useState('');\n const [filterTimeout, setFilterTimeout] = useState();\n\n const [systemSettingEntityIsFrozen, setSystemSettingEntityIsFrozen] = useState(false);\n const userIsAdmin = AuthenticationService.currentUserInfo?.userIsAdmin() ?? false;\n\n // Initialize Command Manager Service\n const {\n initializeCommandManagerServiceOnDispatcher,\n commandManagerService,\n } = useCommandManagerDispatcher({ key: bidPackageDefinitionDispatchKey });\n\n useDegradedActionNotifications('BidPackageMaintenancePage');\n\n // Register dispatch key and reducer function with the Command Manager Service\n useEffect(() => {\n const batchCommandInitializerReducer = generateBatchCommandInitializerReducer(\n BidPackageMaintenanceBatchCommand,\n );\n initializeCommandManagerServiceOnDispatcher(\n bidPackageDefinitionDispatchKey,\n batchCommandInitializerReducer,\n commandManagerDispatchReducer,\n bidPackageMaintenanceReducer,\n );\n }, [initializeCommandManagerServiceOnDispatcher]);\n\n // Executes the batch command of the given command manager\n const executeBatchCommand = useCallback(\n async (commandManagerObj?: CommandManagerService | undefined): Promise => {\n if (!commandManagerObj) {\n return;\n }\n\n // lets create a deep copy of the command manager service\n const newCommandManagerService = commandManagerObj.clone();\n\n const result = await newCommandManagerService.executeNextCommand();\n // If no command was present, null will be returned\n if (result === null) {\n return;\n }\n\n // Update the dispatch data since we just mutated the commands in the command manager\n dispatchAction(\n bidPackageDefinitionDispatchKey,\n {\n data: newCommandManagerService,\n type: 'update-command-manager',\n },\n );\n },\n [dispatchAction],\n );\n\n // Callback method to execute the batch command using the page's command manager\n const executeBatchCommandCallback = useCallback(async () => {\n // bc this method is a callback method used by child components, and reworking that is not critical right now, we need to pass through the page's command manager.\n await executeBatchCommand(commandManagerService);\n }, [executeBatchCommand, commandManagerService]);\n\n const getNewBidPackageDefinition = (): BidPackageDefinition => ({\n id: generateUuid(),\n code: '',\n description: '',\n tradeRequirementDefinitions: [],\n isNew: true,\n });\n\n // Initial load of data\n useEffect(() => {\n const loadBidPackageDefinitions = async (): Promise => {\n try {\n showPageLoadingOverlay();\n\n // NOTE: This page is not wired up to SignalR so we only perform this frozen entity check once on load\n const entityIsFrozen = await FrozenEntitiesApi.checkIfEntityIsFrozen(\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\n );\n\n setSystemSettingEntityIsFrozen(entityIsFrozen);\n\n const definitions = await BidPackageMaintenanceApi.getAllBidPackageDefinitions();\n setBidPackageDefinitions(definitions);\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('general:pageLoadError'));\n history.push(ApplicationRoutes.ERROR_ERROR);\n } finally {\n hidePageLoadingOverlay();\n }\n };\n loadBidPackageDefinitions();\n }, [hidePageLoadingOverlay, showErrorNotification, showPageLoadingOverlay, t, logger, history]);\n\n const toggleCollapse = (open: boolean): void => {\n setIsEditAreaOpen(open);\n\n if (open) {\n setTimeout(() => {\n scrollToRef(bidPackageMaintenancePageEditAreaRef);\n }, 500);\n }\n };\n\n const onSubmit = useCallback(\n async (definition: BidPackageDefinition) => {\n showPageLoadingOverlay();\n\n const closeEditAreaAndClearOutEditModel = (): void => {\n setIsEditAreaOpen(false);\n\n // Delay this slightly so the edit area has time to animate closed\n setTimeout(() => {\n setBidPackageDefinitionToEdit(null);\n }, 250);\n };\n\n try {\n //lets store off the command manager that we will send off to execute its batch command\n let commandManagerObj = commandManagerService;\n\n if (definition.isNew) {\n //lets make sure we have a command manager service\n if (commandManagerObj) {\n // Lets add this to the commands. There shouldn't be any other commands batched up, but to continue with the same paradigm, lets add this command.\n // Lets pass through the batch command class so it can be generated if one doesn't exist.\n commandManagerObj = addCommandToBatchCommandObject(\n commandManagerObj,\n new CreateBidPackageDefinitionCommand(\n definition.code.trim(),\n definition.description.trim(),\n ),\n BidPackageMaintenanceBatchCommand,\n );\n } else {\n // if we got to this point, we are in a bad state, so lets throw an error so we know what happened\n throw new Error('Missing Command Manager Service');\n }\n\n await executeBatchCommand(commandManagerObj);\n definition.isNew = false;\n const updatedBidPackageDefinitions = [...bidPackageDefinitions, definition];\n const sortedDefinitions = sortBy(updatedBidPackageDefinitions, (b) => b.code);\n setBidPackageDefinitions(sortedDefinitions);\n\n showSuccessNotification(\n t('general:success'),\n t('bid-package-maintenance:createBidPackageDefinitionSuccess'),\n );\n } else {\n if (isEqual(definition, bidPackageDefinitionToEdit)) {\n // TODO there might be a potential issue here. Shouldn't we be clearing out the commands if there are any?!? for example, if they change the code of a bid package, and then change it back. There will be two batched up commands.\n // For that reason, we should clear out any pending commands here before returning out. - MR\n closeEditAreaAndClearOutEditModel();\n\n showInfoNotification(\n t('general:noChanges'),\n t('bid-package-maintenance:bidPackageDefinitionNoChanges'),\n );\n return;\n }\n await executeBatchCommand(commandManagerObj);\n const bidPackageDefinitionsClone = [...bidPackageDefinitions];\n const index = bidPackageDefinitionsClone.findIndex((b) => b.id === definition.id);\n if (index === -1) {\n throw new Error(\n t('bid-package-maintenance:bidPackageNotFound', { code: definition.code }),\n );\n }\n\n const bidPackageDefToUpdate = bidPackageDefinitionsClone[index];\n bidPackageDefToUpdate.code = definition.code;\n bidPackageDefToUpdate.description = definition.description;\n\n setBidPackageDefinitions(bidPackageDefinitionsClone);\n\n showSuccessNotification(\n t('general:success'),\n t('bid-package-maintenance:updateBidPackageDefinitionSuccess'),\n );\n }\n closeEditAreaAndClearOutEditModel();\n } catch (error) {\n logger.logError(error);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const errorMessageFromServer = (error as any).response?.data?.detail || '';\n\n // If the error message contains text about a 'unique code', we can give the user a more specific error message and not\n // redirect them to the error page\n if (doesStringExistInOtherString(errorMessageFromServer, 'unique code')) {\n showErrorNotification(t('general:error'), t('bid-package-maintenance:uniqueCodeError'));\n }\n // Otherwise, 💩 hit the fan, time to bail\n else {\n if (definition.isNew) {\n showErrorNotification(\n t('general:error'),\n t('bid-package-maintenance:createBidPackageDefinitionError'),\n );\n } else {\n showErrorNotification(\n t('general:error'),\n t('bid-package-maintenance:updateBidPackageDefinitionError'),\n );\n }\n\n history.push(ApplicationRoutes.ERROR_ERROR);\n }\n } finally {\n hidePageLoadingOverlay();\n }\n },\n [\n showPageLoadingOverlay,\n executeBatchCommand,\n commandManagerService,\n bidPackageDefinitions,\n showSuccessNotification,\n t,\n bidPackageDefinitionToEdit,\n showInfoNotification,\n showErrorNotification,\n hidePageLoadingOverlay,\n logger,\n history,\n ],\n );\n\n const onDiscard = useCallback(\n (bidPackageDefinition: BidPackageDefinition) => {\n const discardChanges = (): void => {\n setIsEditAreaOpen(false);\n\n dispatchAction(\n bidPackageDefinitionDispatchKey,\n {\n data: null,\n type: 'clear-command-manager',\n },\n );\n\n // Delay this slightly so the edit area has time to animate closed\n setTimeout(() => {\n setBidPackageDefinitionToEdit(null);\n }, 250);\n };\n\n if (!isEqual(bidPackageDefinition, bidPackageDefinitionToEdit)) {\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: (): void => {\n discardChanges();\n hideConfirmationOverlay();\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n } else {\n discardChanges();\n }\n },\n [\n bidPackageDefinitionToEdit,\n dispatchAction,\n showConfirmationOverlay,\n t,\n hideConfirmationOverlay,\n ],\n );\n\n const onAddClick = () => {\n setBidPackageDefinitionToEdit(getNewBidPackageDefinition());\n toggleCollapse(true);\n };\n\n const onEditClick = (bidPackageDefinition: BidPackageDefinition) => {\n setBidPackageDefinitionToEdit(bidPackageDefinition);\n toggleCollapse(true);\n };\n\n const onDeleteClick = useCallback(\n (definition: BidPackageDefinition) => {\n showConfirmationOverlay({\n text: t('bid-package-maintenance:confirmDeleteBidPackageDefinition', {\n code: definition.code,\n description: definition.description,\n }),\n buttons: [\n {\n text: t('general:yes'),\n onClick: async (): Promise => {\n hideConfirmationOverlay();\n showPageLoadingOverlay();\n\n try {\n //lets store off the command manager that we will send off to execute its batch command\n let commandManagerObj = commandManagerService;\n\n //lets make sure we have a command manager service\n if (commandManagerObj) {\n // Lets add this to the commands. There shouldn't be any other commands batched up, but to continue with the same paradigm, lets add this command.\n // Lets pass through the batch command class so it can be generated if one doesn't exist.\n commandManagerObj = addCommandToBatchCommandObject(\n commandManagerObj,\n new DeleteBidPackageDefinitionCommand(definition.code),\n BidPackageMaintenanceBatchCommand,\n );\n } else {\n // if we got to this point, we are in a bad state, so lets throw an error so we know what happened\n throw new Error('Missing Command Manager Service');\n }\n\n await executeBatchCommand(commandManagerObj);\n\n const updatedBidPackageDefinitions = bidPackageDefinitions.filter(\n (definitions) => definitions.code !== definition.code,\n );\n setBidPackageDefinitions(updatedBidPackageDefinitions);\n\n showSuccessNotification(\n t('general:success'),\n t('bid-package-maintenance:deleteBidPackageDefinitionSuccess'),\n );\n } catch (error) {\n logger.logError(error);\n\n showErrorNotification(\n t('general:error'),\n t('bid-package-maintenance:deleteBidPackageDefinitionError'),\n );\n\n history.push(ApplicationRoutes.ERROR_ERROR);\n } finally {\n hidePageLoadingOverlay();\n }\n },\n color: 'normal',\n },\n {\n text: t('general:no'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n },\n [\n bidPackageDefinitions,\n executeBatchCommand,\n commandManagerService,\n hideConfirmationOverlay,\n hidePageLoadingOverlay,\n showConfirmationOverlay,\n showErrorNotification,\n showPageLoadingOverlay,\n showSuccessNotification,\n t,\n logger,\n history,\n ],\n );\n\n const onSearchTextChange = useCallback(\n (newSearchText: string): void => {\n const cleanedUpSearchText = newSearchText.toLowerCase();\n\n if (filterTimeout) {\n clearTimeout(filterTimeout);\n }\n\n // Delay the filtering until the user stops typing for a reasonable amount of time\n if (cleanedUpSearchText.length > 0) {\n setFilterTimeout(\n setTimeout(() => {\n setSearchText(cleanedUpSearchText);\n }, 250),\n );\n } else {\n setSearchText(cleanedUpSearchText);\n }\n },\n [filterTimeout],\n );\n\n const getDisplayedBidPackageDefinitions = (searchText: string): BidPackageDefinition[] => {\n const getSortedBidPackageDefinitions = (\n bidPackageDefs: BidPackageDefinition[],\n ): BidPackageDefinition[] => {\n const sortedBidPackageDefs = sortBy(bidPackageDefs, (bp) => bp.code.trim());\n\n sortedBidPackageDefs.forEach((bp) => {\n bp.tradeRequirementDefinitions = sortBy(bp.tradeRequirementDefinitions, (trd) => trd.index);\n });\n\n return sortedBidPackageDefs;\n };\n\n if (isEmptyOrWhitespace(searchText)) {\n return getSortedBidPackageDefinitions(bidPackageDefinitions);\n }\n\n const filteredCollection = bidPackageDefinitions.filter((definition) => {\n if (definition.code.toLowerCase().indexOf(searchText) > -1) {\n return true;\n }\n if (definition.description.toLowerCase().indexOf(searchText) > -1) {\n return true;\n }\n return false;\n });\n\n return getSortedBidPackageDefinitions(filteredCollection);\n };\n\n const filteredBidPackageDefinitions = getDisplayedBidPackageDefinitions(searchText);\n\n return (\n <>\n
    \n {systemSettingEntityIsFrozen ? (\n
    \n
    \n \n
    \n
    \n ) : (\n <>\n )}\n\n
    \n \n
    \n \n
    \n
    \n
    \n {bidPackageDefinitionToEdit ? (\n \n ) : (\n <>\n )}\n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n\n \n\n
    \n \n
    \n
    \n \n );\n};\n\nexport default BidPackageMaintenancePage;\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateFeeDefinitionAmountCommand extends CommandBase {\n constructor(public name: string, public amount: number) {\n super('DESTINI.BidDay.Commands.BidDaySystem.UpdateFeeDefinitionAmount', '', 'post');\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateFeeDefinitionOrderCommand extends CommandBase {\n constructor(public name: string, public order: number) {\n super('DESTINI.BidDay.Commands.BidDaySystem.UpdateFeeDefinitionOrder', '', 'post');\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateFeeDefinitionNameCommand extends CommandBase {\n constructor(public name: string, public updatedName: string) {\n super('DESTINI.BidDay.Commands.BidDaySystem.UpdateFeeDefinitionName', '', 'post');\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateFeeDefinitionFeeTypeCommand extends CommandBase {\n constructor(public name: string, public feeType: number, public referenceFeeName?: string) {\n super('DESTINI.BidDay.Commands.BidDaySystem.UpdateFeeDefinitionFeeType', '', 'post');\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class CreateFeeDefinitionCommand extends CommandBase {\n constructor(public name: string, public feeType: number, public referenceFeeName?: string) {\n super('DESTINI.BidDay.Commands.BidDaySystem.CreateFeeDefinition', '', 'post');\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class DeleteFeeDefinitionCommand extends CommandBase {\n constructor(public name: string) {\n super('DESTINI.BidDay.Commands.BidDaySystem.DeleteFeeDefinition', '', 'post');\n }\n}\n","import { CommandBatchBase } from '../../CommandBatchBase';\nimport { UpdateFeeDefinitionAmountCommand } from '../commands/update-fee-definition-amount-command';\nimport { UpdateFeeDefinitionOrderCommand } from '../commands/update-fee-definition-order-command';\nimport { UpdateFeeDefinitionNameCommand } from '../commands/update-fee-definition-name-command';\nimport { UpdateFeeDefinitionFeeTypeCommand } from '../commands/update-fee-definition-type-command';\nimport { CreateFeeDefinitionCommand } from '../commands/create-fee-definition-command';\nimport { DeleteFeeDefinitionCommand } from '../commands/delete-fee-definition-command';\n\nexport class FeesBatchCommand extends CommandBatchBase {\n constructor() {\n super('fee-maintenance-batch', '/bidDaySystemSettings', 'post', [\n CreateFeeDefinitionCommand,\n DeleteFeeDefinitionCommand,\n UpdateFeeDefinitionNameCommand,\n UpdateFeeDefinitionAmountCommand,\n UpdateFeeDefinitionFeeTypeCommand,\n UpdateFeeDefinitionOrderCommand,\n ]);\n }\n}\n","import { TFunction } from 'i18next';\r\nimport { FeeTypes } from '../app/enums/fee-enum';\r\n\r\nconst convertFeeTypeToFeeTypeOption = (\r\n t: TFunction,\r\n feeType: number,\r\n referenceFeeName?: string,\r\n): FeeTypeOption => {\r\n if (feeType === FeeTypes.Bid) {\r\n return {\r\n name: t('general:bid'),\r\n text: t('fees:feeType_Bid'),\r\n value: FeeTypes.Bid,\r\n };\r\n } else if (feeType === FeeTypes.Total) {\r\n return {\r\n name: t('general:total'),\r\n text: t('fees:feeType_PercentOfTotal'),\r\n value: FeeTypes.Total,\r\n };\r\n } else if (feeType === FeeTypes.Percent) {\r\n // a reference fee name must be provided\r\n if (!referenceFeeName) {\r\n throw Error('the reference fee must be provided when the fee type is Percent');\r\n }\r\n return {\r\n name: referenceFeeName,\r\n text: t('fees:feeType_PercentOfReferenceFeeName', {\r\n referenceFeeName: referenceFeeName,\r\n }),\r\n value: FeeTypes.Percent,\r\n };\r\n } else if (feeType === FeeTypes.Subtotal) {\r\n return {\r\n name: t('general:subtotal'),\r\n text: t('general:subtotal'),\r\n value: FeeTypes.Subtotal,\r\n };\r\n } else if (feeType === FeeTypes.LumpSum) {\r\n return {\r\n name: t('fees:lump'),\r\n text: t('fees:feeType_LumpSum'),\r\n value: FeeTypes.LumpSum,\r\n };\r\n }\r\n\r\n throw Error('unable to find the equivalent fee type');\r\n};\r\n\r\n// convert fee type and reference fee (if applicable) into the fee type name\r\nconst convertFeeTypeToFeeTypeName = (\r\n t: TFunction,\r\n feeType: FeeTypes,\r\n referenceFeeName?: string,\r\n): string => {\r\n switch (feeType) {\r\n case FeeTypes.Bid:\r\n return t('fees:feeType_Bid');\r\n\r\n case FeeTypes.Total:\r\n return t('fees:feeType_PercentOfTotal');\r\n\r\n case FeeTypes.Percent: {\r\n // a reference fee name must be provided\r\n if (!referenceFeeName) {\r\n throw Error('the reference fee must be provided when the fee type is Percent');\r\n }\r\n return t('fees:feeType_PercentOfReferenceFeeName', {\r\n referenceFeeName: referenceFeeName,\r\n });\r\n }\r\n\r\n case FeeTypes.Subtotal:\r\n return t('general:subtotal');\r\n\r\n case FeeTypes.LumpSum:\r\n return t('fees:feeType_LumpSum');\r\n\r\n default:\r\n throw Error('unable to find the equivalent fee type');\r\n }\r\n};\r\n\r\nexport { convertFeeTypeToFeeTypeName, convertFeeTypeToFeeTypeOption };\r\n","import { NumericTextBox, NumericTextBoxProps } from '@progress/kendo-react-inputs';\r\nimport { NumberFormatOptions } from '@progress/kendo-react-intl';\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport GeneralConstants from '../../../constants/general';\r\nimport { convertToPercentage } from '../../../utils/math';\r\nimport { generateUuid } from '../../../utils/uuid';\r\nimport './BTNumericInput.scss';\r\n\r\nexport type BTNumericInputFormat = 'none' | 'decimal' | 'decimal-5' | 'percent' | 'currency';\r\n\r\ninterface Props {\r\n textAlignment?: 'left' | 'right';\r\n // NOTE: There is a \"format\" property on NumericTextBoxProps but we override it so we don't have to explicitly\r\n // pass in a NumberFormatOptions object and can instead pass in a nice type string\r\n format?: BTNumericInputFormat;\r\n onKeyDown?: (e: KeyboardEvent) => void;\r\n allowAnyKeysToPassThrough?: boolean;\r\n nonNumericKeysToPassThrough?: string[]; // A list of keys that we want to trigger the onKeyDown prop\r\n}\r\n\r\n// A very basic wrapped Kendo input element that we can use independently of Formik,\r\nconst BTNumericInput: React.FC = ({\r\n onKeyDown,\r\n allowAnyKeysToPassThrough,\r\n ...props\r\n}) => {\r\n const classNames = props.className ? props.className.split(' ') : [];\r\n\r\n // NOTE: If this is a 'percent' numeric, add a new class name that adds some new special styling.\r\n if (props.format === 'percent') {\r\n classNames.push('percentInput');\r\n }\r\n\r\n const textAlignment = props.textAlignment !== undefined ? props.textAlignment : 'right';\r\n\r\n const [nonNumericKeysToPassThrough] = useState(\r\n props.nonNumericKeysToPassThrough !== undefined ? props.nonNumericKeysToPassThrough : [],\r\n );\r\n\r\n let formatStringForNumericComponent: NumberFormatOptions | string | undefined = undefined;\r\n\r\n switch (props.format) {\r\n case 'percent':\r\n // NOTE: For percents, we want to make the format be a decimal and take care of adding the percent symbol ourselves (see class name above).\r\n // The reason for this was an error with the Kendo NumericTextBox control and having a single digit and the percent symbol selected.\r\n // If a (digit) keypress was made, in that scenario, the digit would be \"swallowed\" and the cursor would go between the current\r\n // digit and percent symbol. Any other combination of selections (multiple digits, multiple digits and the percent symbol, negative\r\n // numbers, etc.) worked as expected: the selection would be overwritten with whatever (digit) key was pressed.\r\n formatStringForNumericComponent = {\r\n style: 'decimal',\r\n minimumFractionDigits: GeneralConstants.PERCENT_MINIMUM_FRACTION_DIGITS,\r\n maximumFractionDigits: GeneralConstants.PERCENT_MAXIMUM_FRACTION_DIGITS,\r\n };\r\n break;\r\n\r\n case 'currency':\r\n formatStringForNumericComponent = {\r\n style: 'currency',\r\n };\r\n break;\r\n\r\n // NOTE: For decimals, we want to set a format with 2 decimal places explicitly because using the Kendo 'decimal' style\r\n // only provides decimal points as needed and doesn't always show them\r\n case 'decimal':\r\n formatStringForNumericComponent = 'n2';\r\n break;\r\n\r\n case 'decimal-5':\r\n formatStringForNumericComponent = {\r\n minimumFractionDigits: GeneralConstants.DECIMAL_PRECISION_FORMAT.MINIMUM_FRACTION_DIGITS,\r\n maximumFractionDigits: GeneralConstants.DECIMAL_PRECISION_FORMAT.MAXIMUM_FRACTION_DIGITS,\r\n };\r\n break;\r\n }\r\n\r\n if (textAlignment === 'left') {\r\n classNames.push('leftJustify');\r\n }\r\n\r\n const [inputIdentifier] = useState(\r\n props.id || props.name || props.label || generateUuid(),\r\n );\r\n\r\n const inputRef: React.MutableRefObject = useRef(null);\r\n\r\n // NOTE: The Kendo NumericTextBox component allows us to have an empty value, but it will change the value to '0' if we press the\r\n // up or down arrow keys and the value is empty, regardless if we disable its ability to increment or decrement the value when\r\n // arrow keys are used (via the 'step' property).\r\n // There is no way to disable this functionality so we have to jump through a bunch of hoops here to know what the last key pressed was\r\n // and do special logic in the change handler function if the last key was the up or down arrow to prevent it from changing.\r\n const [lastKeyPressedWasUpOrDownArrowKey, setLastKeyPressedWasUpOrDownArrowKey] = useState(false);\r\n\r\n useEffect(() => {\r\n if (inputRef.current) {\r\n const onKeyDownHandler = (e: KeyboardEvent) => {\r\n // If the key pressed wasn't on the whitelist and wasn't numeric, we stop the event from bubbling up and affecting the\r\n // value of this input (it would blank out any numbers after the position at which a letter was entered)\r\n if (\r\n !(\r\n allowedNonNumericKeys.find((v) => v.toUpperCase() === e.key.toUpperCase()) ||\r\n ([\r\n GeneralConstants.KEY_A,\r\n GeneralConstants.KEY_C,\r\n GeneralConstants.KEY_V,\r\n GeneralConstants.KEY_X,\r\n ].includes(e.key.toUpperCase()) &&\r\n e.ctrlKey) ||\r\n // Any of the function keys (F5, etc.)\r\n /^F\\d{1,2}/gi.test(e.key) ||\r\n // Any numeric character\r\n /^\\d$/g.test(e.key)\r\n )\r\n ) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }\r\n\r\n if (allowAnyKeysToPassThrough) {\r\n if (onKeyDown) {\r\n onKeyDown(e);\r\n return;\r\n }\r\n }\r\n\r\n // If the user wants to be notified when certain keys are pressed, call the onKeyDown callback function.\r\n // NOTE: We only do this when this component knows to look for specific values.\r\n // NOTE: If the key presses that the user wants to be notified about were outside the allowed default values above, they will\r\n // not bubble up in JS\r\n if (\r\n onKeyDown &&\r\n nonNumericKeysToPassThrough.find((v) => v.toLowerCase() === e.key.toLowerCase())\r\n ) {\r\n onKeyDown(e);\r\n }\r\n\r\n setLastKeyPressedWasUpOrDownArrowKey(\r\n [GeneralConstants.KEY_ARROW_UP, GeneralConstants.KEY_ARROW_DOWN].includes(e.key),\r\n );\r\n };\r\n\r\n // Get a local reference to the current value so we can return it inside a cleanup function and have the right reference.\r\n // NOTE: The kendo control does not supply a keydown event so we have to hook into it on the underlying input ref.\r\n const currentInput = inputRef.current;\r\n currentInput.addEventListener('keydown', onKeyDownHandler);\r\n\r\n return () => {\r\n currentInput?.removeEventListener('keydown', onKeyDownHandler);\r\n };\r\n }\r\n }, [allowAnyKeysToPassThrough, nonNumericKeysToPassThrough, onKeyDown]);\r\n\r\n let valToPassToInput = props.value;\r\n\r\n // Since we're styling the percent types as a number, when we display the value, we need to multiply it by 100 so it displays properly (ex: 0.03 * 100 is the same as 3%).\r\n if (props.format === 'percent') {\r\n if (!isNaN(valToPassToInput as number)) {\r\n valToPassToInput = (valToPassToInput as number) * 100;\r\n }\r\n }\r\n\r\n return (\r\n // Fall back to using the label for the input name\r\n
    \r\n {props.label ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n {/* NOTE: The step prop value of 0 causes the input to not increment or decrement the value when the up and down arrow keys are used */}\r\n {\r\n event.target?.element?.select();\r\n\r\n // Bubble the focus event up\r\n if (props.onFocus) {\r\n props.onFocus(event);\r\n }\r\n }}\r\n onChange={(e) => {\r\n // NOTE: Due to the fact that Kendo will change the value to '0' when the current value is empty and the up or down arrow is pressed,\r\n // we have to override this functionality so any event handlers up the chain get the proper value passed along and not have the value changed\r\n // to '0'.\r\n if (props.onChange) {\r\n if (e.target.value === 0 && lastKeyPressedWasUpOrDownArrowKey) {\r\n props.onChange({\r\n ...e,\r\n target: { ...e.target, value: null },\r\n value: null,\r\n });\r\n } else {\r\n // Since we're styling the percent types as a number, when we save the value, we need to divide it by 100 so it saves properly (ex: 3% / 100 is the same as 0.03).\r\n if (props.format === 'percent') {\r\n // the default value of e.target.value when the textbox is empty is null, so set default it to null.\r\n let val: number | null = null;\r\n if (e.target.value) {\r\n const parsedFloat = parseFloat(e.target.value.toString());\r\n val = convertToPercentage(parsedFloat);\r\n }\r\n\r\n props.onChange({\r\n ...e,\r\n target: { ...e.target, value: val },\r\n value: val,\r\n });\r\n } else {\r\n props.onChange(e);\r\n }\r\n }\r\n }\r\n }}\r\n id={inputIdentifier}\r\n className={classNames.join(' ')}\r\n name={inputIdentifier}\r\n step={0}\r\n ref={(e) => {\r\n if (e) {\r\n inputRef.current = (e.element as unknown) as HTMLInputElement;\r\n\r\n if (inputIdentifier && e?.element && !e.element.getAttribute('data-testid')) {\r\n e.element.setAttribute('data-testid', inputIdentifier);\r\n }\r\n }\r\n }}\r\n spinners={false}\r\n format={formatStringForNumericComponent}\r\n />\r\n
    \r\n );\r\n};\r\n\r\nconst allowedNonNumericKeys: string[] = [\r\n GeneralConstants.KEY_ARROW_DOWN,\r\n GeneralConstants.KEY_ARROW_LEFT,\r\n GeneralConstants.KEY_ARROW_RIGHT,\r\n GeneralConstants.KEY_ARROW_UP,\r\n GeneralConstants.KEY_BACKSPACE,\r\n GeneralConstants.KEY_DELETE,\r\n GeneralConstants.KEY_ENTER,\r\n GeneralConstants.KEY_HYPHEN,\r\n GeneralConstants.KEY_PERIOD,\r\n GeneralConstants.KEY_TAB,\r\n // NOTE: A and B are needed for the konami code easter egg\r\n GeneralConstants.KEY_A,\r\n GeneralConstants.KEY_B,\r\n];\r\n\r\nexport default BTNumericInput;\r\n","import { NumericTextBoxChangeEvent } from '@progress/kendo-react-inputs';\nimport { InputChangeEvent } from '@progress/kendo-react-inputs/dist/npm/input/interfaces/InputChangeEvent';\nimport { clone } from 'lodash';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport EntityValidationConstants from '../../../../constants/general/entity-validation-constants';\nimport { formatNumberAsCurrencyFull } from '../../../../utils/general';\nimport { FeeTypes } from '../../../enums/fee-enum';\nimport BTIconButton from '../../controls/icon-button/BTIconButton';\nimport BTDropDownList, { BTDropDownListOption } from '../../inputs/BTDropDownList';\nimport BTInput from '../../inputs/BTInput';\nimport BTNumericInput from '../../inputs/BTNumericInput';\nimport './FeeTableItem.scss';\n\ninterface Props {\n fee: FeeDefinitionInfo;\n feeTypeDropDownListOptions: BTDropDownListOption[];\n errors: FeeError[];\n hasErrors: boolean;\n isAdding: boolean;\n addFee: (fee: FeeDefinitionInfo) => void;\n deleteFee: (fee: FeeDefinitionInfo) => void;\n updateFee: (fee: FeeDefinitionInfo, updatedFee: FeeDefinitionInfo) => void;\n validateFee: (fee: FeeDefinitionInfo) => boolean;\n isReadOnly: boolean;\n}\n\nconst FeeTableItem: React.FC = ({\n fee,\n feeTypeDropDownListOptions,\n errors,\n hasErrors,\n isAdding,\n addFee,\n deleteFee,\n updateFee,\n validateFee,\n isReadOnly,\n}) => {\n const { t } = useTranslation();\n const [feeToEdit, setFeeToEdit] = useState(fee);\n const [validFee, setValidFee] = useState(fee);\n\n // When the fee prop is updated, overwrite existing changes with the new state\n useEffect(() => {\n if (!hasErrors && !fee.isNew) {\n setFeeToEdit(fee);\n setValidFee(fee);\n }\n }, [hasErrors, fee]);\n\n const updateLocalAndParentState = useCallback(\n (updatedFee: FeeDefinitionInfo) => {\n if (updatedFee.isNew) {\n if (updatedFee.name.length > 0) {\n addFee(updatedFee);\n }\n } else {\n if (validateFee(updatedFee)) {\n // Update the fee in the parent component\n updateFee(validFee, updatedFee);\n // Store the latest valid state in case the next entry is invalid and needs to be corrected\n setValidFee(updatedFee);\n }\n }\n },\n [addFee, updateFee, validFee, validateFee],\n );\n\n const nameChangeHandler = useCallback(\n (event: InputChangeEvent) => {\n const updatedFee: FeeDefinitionInfo = clone(feeToEdit);\n updatedFee.name = event.value;\n\n setFeeToEdit(updatedFee);\n },\n [feeToEdit],\n );\n\n const amountChangeHandler = useCallback(\n (event: NumericTextBoxChangeEvent) => {\n const updatedFee: FeeDefinitionInfo = clone(feeToEdit);\n updatedFee.amount = event.target.value || 0;\n\n setFeeToEdit(updatedFee);\n },\n [feeToEdit],\n );\n\n const typeChangeHandler = useCallback(\n (value: unknown) => {\n const option = value as FeeTypeOption;\n if (option) {\n const updatedFee: FeeDefinitionInfo = clone(feeToEdit);\n updatedFee.feeType = option;\n\n if (option.value === FeeTypes.Percent) {\n updatedFee.referenceFee = option.name;\n } else {\n updatedFee.referenceFee = undefined;\n }\n\n // if we are changing to/from a lumpsum\n if (\n (feeToEdit.feeType.value === FeeTypes.LumpSum) !==\n (option.value === FeeTypes.LumpSum)\n ) {\n updatedFee.amount = 0;\n }\n setFeeToEdit(updatedFee);\n updateLocalAndParentState(updatedFee);\n }\n },\n [feeToEdit, updateLocalAndParentState],\n );\n\n return (\n
    \n
    \n {\n const cleanedUpFee: FeeDefinitionInfo = {\n ...feeToEdit,\n name: (feeToEdit.name || '').trim(),\n };\n updateLocalAndParentState(cleanedUpFee);\n }}\n disabled={\n isReadOnly || (!hasErrors && errors.length > 0) || (isAdding && !feeToEdit.isNew)\n }\n autoFocus={feeToEdit.isNew}\n maxLength={EntityValidationConstants.FeeEntityLimits.Name_MaxLength}\n />\n
    \n {feeToEdit.feeType.value === FeeTypes.Subtotal ? (\n
    \n ) : (\n
    \n 0 || (isAdding && !feeToEdit.isNew)}\n />\n
    \n )}\n {feeToEdit.feeType.value === FeeTypes.Subtotal ? (\n
    \n ) : (\n
    \n updateLocalAndParentState(feeToEdit)}\n disabled={isReadOnly || errors.length > 0 || (isAdding && !feeToEdit.isNew)}\n />\n
    \n )}\n
    \n \n
    \n
    \n {\n deleteFee(feeToEdit);\n }}\n data-testid={'delete-fee-data-testid'}\n disabled={isReadOnly || errors.length > 0 || (isAdding && !feeToEdit.isNew)}\n />\n
    \n
    \n );\n};\n\nexport default FeeTableItem;\n","import Big from 'big.js';\nimport { cloneDeep, isEqual, omit, uniq } from 'lodash';\nimport React, { useCallback, useContext, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { formatNumberAsCurrency, formatNumberAsCurrencyFull } from '../../../utils/general';\nimport { isEmptyOrWhitespace } from '../../../utils/strings';\nimport { generateUuid } from '../../../utils/uuid';\nimport { FeeTypes } from '../../enums/fee-enum';\nimport { ConfirmationOverlayContext } from '../confirmation-overlay/ConfirmationOverlayContext';\nimport BTButton from '../controls/button/BTButton';\nimport { BTDropDownListOption } from '../inputs/BTDropDownList';\nimport BTNumericInput from '../inputs/BTNumericInput';\nimport { NotificationPanelContext } from '../notification-panel/NotificationPanelContext';\nimport BTSortableContainer, { BTSortableItem } from '../sortable/BTSortableContainer';\nimport FeeTableItem from './components/FeeTableItem';\nimport './FeeTable.scss';\n\nexport const DEFAULT_BID_TOTAL = 1_000_000;\n\nexport interface Fee {\n id: string;\n order: number;\n name: string;\n amount: number;\n feeType: FeeTypeOption;\n referenceFee?: string;\n total: number;\n isNew: boolean;\n}\n\ninterface Props {\n initialFees: Fee[];\n addFeeCallback: (fee: Fee) => void;\n deleteFeeCallback: (fee: Fee) => void;\n updateFeeCallback: (fee: Fee, updatedFee: Fee) => void;\n onSortEndCallback: (fee: Fee, index: number) => void;\n calculateFeesCallback: (updatedFees: Fee[], baseCost: number) => Promise;\n onSaveClick: (fees: Fee[]) => void;\n discardCallback: () => void;\n bidTotal?: number;\n isReadOnly?: boolean;\n}\n\nconst generateFeesTotal = (bidTotal: number, fees: Fee[]): Big => {\n return new Big(bidTotal).add(\n fees.reduce((sum, cur) => {\n return cur.feeType?.value === FeeTypes.Subtotal ? sum : sum.add(new Big(cur.total));\n }, new Big(0)),\n );\n};\n\nconst FeeTable: React.FC = ({\n initialFees,\n addFeeCallback,\n deleteFeeCallback,\n updateFeeCallback,\n onSortEndCallback,\n calculateFeesCallback,\n onSaveClick,\n discardCallback,\n ...props\n}) => {\n const isReadOnly = props.isReadOnly ?? false;\n const { showErrorNotification } = useContext(NotificationPanelContext);\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n const { t } = useTranslation();\n\n const DEFAULT_FEETYPE_SELECTION: FeeTypeOption = useMemo(\n () => ({\n name: t('fees:bid'),\n text: t('fees:feeType_Bid'),\n value: FeeTypes.Bid,\n }),\n [t],\n );\n\n const [bidTotal, setBidTotal] = useState(props.bidTotal ?? DEFAULT_BID_TOTAL);\n const [fees, setFees] = useState(cloneDeep(initialFees));\n const [errors, setErrors] = useState([]);\n const [isAddingFeeOrSubtotal, setIsAddingFeeOrSubtotal] = useState(false);\n\n /**\n * This ref is used to keep track of the user's most recent actions on the fees, as multiple actions can fire before the `setFees` hook.\n */\n const feesRef = useRef(initialFees);\n\n /**\n * This ref is used to keep track of what the most recent call to calculate fees should be.\n */\n const calculateFeesPromiseRef = useRef | null>(null);\n\n const feeTypeOptions: FeeTypeOption[] = useMemo(() => {\n return [\n DEFAULT_FEETYPE_SELECTION,\n {\n name: t('general:total'),\n text: t('fees:feeType_PercentOfTotal'),\n value: FeeTypes.Total,\n },\n { name: t('fees:lump'), text: t('fees:feeType_LumpSum'), value: FeeTypes.LumpSum },\n ...fees.map((fee) => ({\n name: fee.name,\n text: t('fees:feeType_PercentOfReferenceFeeName', { referenceFeeName: fee.name }),\n value: FeeTypes.Percent,\n })),\n ];\n }, [DEFAULT_FEETYPE_SELECTION, fees, t]);\n\n const feeTypeDropDownListOptions: BTDropDownListOption[] = useMemo(() => {\n return feeTypeOptions.map((option) => ({ name: option.text, value: option }));\n }, [feeTypeOptions]);\n\n // Returns a collection of BTDropDownListOptions for a fee's type input that excludes the given fee\n const getFilteredFeeTypeDropDownListOptions = useCallback(\n (name: string): BTDropDownListOption[] => {\n // Filter out potential self-references\n const filteredOptions: BTDropDownListOption[] = feeTypeDropDownListOptions.filter((o) =>\n feeTypeOptions.find((t) => o.name === t.text && t.name !== name),\n );\n\n return filteredOptions;\n },\n [feeTypeDropDownListOptions, feeTypeOptions],\n );\n\n const feeHasErrors = useCallback(\n (id: string): boolean => {\n return errors.find((e) => e.id === id) !== undefined;\n },\n [errors],\n );\n\n const setFeeErrors = useCallback(\n (id: string, errorMessages: string[]): void => {\n // Remove old errors\n let updatedErrors = errors.filter((u) => u.id !== id);\n\n // Add new errors\n updatedErrors = updatedErrors.concat(\n errorMessages.map((e) => {\n return { id: id, message: e };\n }),\n );\n\n setErrors(updatedErrors);\n },\n [errors],\n );\n\n const validateFee = useCallback(\n (fee: Fee): boolean => {\n const errorMessages: string[] = [];\n const trimmedName = (fee.name || '').trim().toLowerCase();\n\n // Check if the name is empty or whitespace\n if (trimmedName.length === 0 && !fee.isNew) {\n errorMessages.push(t('fees:emptyDescriptionError'));\n }\n\n // Map the fees, trimmed and converted to lower case to account for whitespace and different casings,\n // skipping the fee that's calling this method, as we don't want to invalidate it for \"having the same name\" if only the value changed.\n const names: string[] = fees\n ? fees!.filter((f) => f.id !== fee.id).map((f) => (f?.name || '').trim().toLowerCase())\n : [];\n\n if (fee.isNew) {\n if (names.indexOf(trimmedName) !== -1) {\n errorMessages.push(t('fees:duplicateDescriptionError'));\n }\n } else {\n let duplicateNames = [];\n duplicateNames = names.filter((item, index) => item === trimmedName && index !== fee.order);\n\n if (duplicateNames.length > 0) {\n errorMessages.push(t('fees:duplicateDescriptionError'));\n }\n }\n\n setFeeErrors(fee.id, errorMessages);\n if (errorMessages.length > 0) {\n return false;\n }\n return true;\n },\n [t, fees, setFeeErrors],\n );\n\n /**\n Passes fees to the page and receives calculated fees back in return, which then updates the state and refs with these newest values.\n Since multiple events can execute this function, we want to be sure that we're keeping the \"most recent\" value, and discarding the older values. (i.e. not updating state and refs)\n */\n const calculateFees = useCallback(\n (updatedFees: Fee[]) => {\n // save off our \"most recently modified\" fees to our ref.\n feesRef.current = cloneDeep(updatedFees);\n\n const currentPromise = calculateFeesCallback(updatedFees, bidTotal);\n calculateFeesPromiseRef.current = currentPromise;\n\n currentPromise.then((feesCallbackResponse) => {\n // we want to ensure that only the most recent fee calculation response is used.\n if (calculateFeesPromiseRef.current && currentPromise === calculateFeesPromiseRef.current) {\n // grab any changes that might have happened after this promise.\n const mostRecentFees = [...feesRef.current];\n\n // Here we just need to apply the calculations to the appropriate fees.\n mostRecentFees.forEach((fee) => {\n const feeCallbackResponse = feesCallbackResponse.find(\n (responseFee) => responseFee.id === fee.id,\n );\n if (feeCallbackResponse) {\n fee.total = feeCallbackResponse.total;\n }\n });\n\n // update fees state, fees ref, and clean out this promise ref.\n setFees(mostRecentFees);\n feesRef.current = cloneDeep(mostRecentFees);\n calculateFeesPromiseRef.current = null;\n }\n });\n },\n [calculateFeesCallback, bidTotal],\n );\n\n const addFee = useCallback(\n (fee: Fee) => {\n const updatedFees = feesRef.current ? [...feesRef.current] : [];\n\n const isValid = validateFee(fee);\n if (isValid) {\n fee.isNew = false;\n addFeeCallback(fee);\n setIsAddingFeeOrSubtotal(false);\n }\n\n updatedFees.splice(fee.order, 1, fee);\n\n // we only want to calculate the fee if the new fee is valid and is a subtotal.\n // we also need to check if the value isn't 0 because if the user changes the amount first,\n // then the name, we'll come into this method but not recalculate the fee.\n if (\n isValid &&\n (fee.feeType.value === FeeTypes.Subtotal || (fee.name.length > 0 && fee.amount !== 0))\n ) {\n calculateFees(updatedFees);\n } else {\n setFees(updatedFees);\n feesRef.current = cloneDeep(updatedFees);\n }\n },\n [addFeeCallback, validateFee, calculateFees],\n );\n\n const deleteFee = useCallback(\n (fee: Fee) => {\n const feeIsReferenced = fees.find((f) => f.referenceFee === fee.name);\n\n // If the fee is being referenced, deny the delete and show a notification\n if (feeIsReferenced) {\n showErrorNotification(t('fees:unableToDeleteHeader'), t('fees:unableToDeleteError'));\n } else {\n let updatedFees: Fee[] = feesRef.current ? [...feesRef.current] : [];\n\n //Filter out the deleted fee\n updatedFees = updatedFees.filter((f) => f.id !== fee.id);\n\n //Reset the index property based on the new collection\n if (updatedFees) {\n updatedFees.forEach((f, idx) => (f.order = idx));\n }\n\n //If we are deleting a fee with isNew set to true, we are no longer adding a fee\n if (fee.isNew) {\n setIsAddingFeeOrSubtotal(false);\n }\n\n //lets remove any errors tied to the fee being deleted\n const updatedErrors = errors.filter((e) => e.id !== fee.id);\n setErrors(updatedErrors);\n\n // we need to let the page know first that the fee is being deleted\n // except in the case of a new fee with no name, as no corresponding 'create-fee-definition' command has been added to the stack\n if (!fee.isNew && !isEmptyOrWhitespace(fee.name)) {\n deleteFeeCallback(fee);\n }\n\n // we need to calculate the fees since we were able to delete a valid fee\n calculateFees(updatedFees);\n }\n },\n [deleteFeeCallback, errors, fees, showErrorNotification, t, calculateFees],\n );\n\n const updateFee = useCallback(\n (fee: Fee, updatedFee: Fee) => {\n const feesClone: Fee[] = feesRef.current ? [...feesRef.current] : [];\n\n const index = feesClone.findIndex((f) => f.id === fee.id);\n feesClone.splice(index, 1, updatedFee);\n\n if (validateFee(updatedFee)) {\n // Dispatch all update commands in the parent component\n updateFeeCallback(fee, updatedFee);\n\n //If the name has changed\n if (fee.name !== updatedFee.name) {\n //Update feeTypeOptions to maintain consistency\n const index = feeTypeOptions.findIndex((f) => f.name === fee.name);\n const updatedFeeTypeOption: FeeTypeOption = {\n ...feeTypeOptions[index],\n name: updatedFee.name,\n text: t('fees:feeType_PercentOfReferenceFeeName', {\n referenceFeeName: updatedFee.name,\n }),\n };\n\n // Update any other referenceFee property of other fees that use this as a referenced fee\n // theres no need to add a command to update the reference fee name across the different fees, bc the update name command should handle that\n const feesToUpdate = feesClone.filter((f) => f.referenceFee === fee.name);\n feesToUpdate.forEach((f) => {\n const index = feesClone.indexOf(f);\n feesClone[index] = {\n ...f,\n feeType: updatedFeeTypeOption,\n referenceFee: updatedFee.name,\n };\n });\n }\n\n // If the fee index, amount, type, or the reference fee has changed, recalculate fees\n if (\n fee.order !== updatedFee.order ||\n fee.amount !== updatedFee.amount ||\n fee.feeType !== updatedFee.feeType ||\n fee.referenceFee !== updatedFee.referenceFee\n ) {\n // NOTE: CalculateFees will update the local fees ref variable\n calculateFees(feesClone);\n } else {\n // Update the fees with the new values if we didn't need to actually calculate anything (ex. a fee description change)\n feesRef.current = cloneDeep(feesClone);\n setFees(feesClone);\n }\n } else {\n // We need to set the fees regardless of whether the fee is valid or not, bc the component needs to hold the most up-to-date fees.\n feesRef.current = cloneDeep(feesClone);\n setFees(feesClone);\n }\n },\n [calculateFees, feeTypeOptions, t, updateFeeCallback, validateFee],\n );\n\n //Handles generation of new Fees or Subtotals\n const generateNewFeeOrSubtotal = useCallback(\n (isSubtotal: boolean): void => {\n const updatedFees = feesRef.current ? [...feesRef.current] : [];\n const newFee: Fee = {\n id: generateUuid(),\n order: fees ? fees.length : 0,\n name: '',\n feeType: isSubtotal\n ? { name: t('general:subtotal'), text: t('general:subtotal'), value: FeeTypes.Subtotal }\n : DEFAULT_FEETYPE_SELECTION,\n amount: 0,\n total: 0,\n isNew: true,\n };\n\n updatedFees.push(newFee);\n setFees(updatedFees);\n setIsAddingFeeOrSubtotal(true);\n\n feesRef.current = cloneDeep(updatedFees);\n },\n [DEFAULT_FEETYPE_SELECTION, fees, t],\n );\n\n // Returns true if fees have been modified\n const feesHaveBeenModified = useCallback(() => {\n const result = !isEqual(\n fees.map((f) => omit(f, 'total')),\n initialFees.map((f) => omit(f, 'total')),\n );\n\n return result;\n }, [fees, initialFees]);\n\n // Maintains the state of the fees after the user has moved a fee\n const onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {\n if (fees) {\n const updatedFees = feesRef.current ? [...feesRef.current] : [];\n const previousFee = fees[oldIndex];\n\n if (oldIndex < 0) {\n oldIndex += updatedFees.length;\n }\n if (newIndex < 0) {\n newIndex += updatedFees.length;\n }\n updatedFees.splice(newIndex, 0, updatedFees.splice(oldIndex, 1)[0]);\n\n //Reset the index property based on the new collection\n if (updatedFees) {\n updatedFees.forEach((f, idx) => (f.order = idx));\n }\n\n onSortEndCallback(previousFee, newIndex);\n\n // we only want to recalculate the fees if there are any subtotals\n if (updatedFees.find((x) => x.feeType.value === FeeTypes.Subtotal)) {\n calculateFees(updatedFees);\n } else {\n setFees(updatedFees);\n feesRef.current = cloneDeep(updatedFees);\n }\n }\n };\n\n const generatedFeeTable: BTSortableItem[] = fees\n ? fees.map((fee: Fee) => {\n const item: BTSortableItem = {\n value: (\n \n ),\n key: fee.id,\n };\n return item;\n })\n : [];\n\n return (\n
    \n
    \n
    \n {\n const isSubtotal = false;\n generateNewFeeOrSubtotal(isSubtotal);\n }}\n disabled={isReadOnly || errors.length > 0 || isAddingFeeOrSubtotal}\n data-testid={'add-fee-data-testid'}\n />\n {\n const isSubtotal = true;\n generateNewFeeOrSubtotal(isSubtotal);\n }}\n disabled={isReadOnly || errors.length > 0 || isAddingFeeOrSubtotal}\n data-testid={'add-subtotal-data-testid'}\n />\n
    \n
    \n {/* To have this label appear beside the editor instead of above it and still have the label represent the editor, we'll create the label instead of using the built in one for the bt numeric input*/}\n \n {\n const value = event.target.value;\n if (value) {\n setBidTotal(value);\n }\n }}\n onBlur={() => {\n if (!fees) {\n return;\n }\n\n calculateFees(fees);\n }}\n />\n
    \n
    \n\n {!fees || fees.length === 0 ? (\n
    {t('fees:noFeesFoundMessage')}
    \n ) : (\n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n \n\n {fees ? (\n
    \n
    \n \n
    \n
    \n \n {\n // show the minimum amount of fractional digits, for the grand total that's displayed to the user.\n formatNumberAsCurrency(generateFeesTotal(bidTotal, fees))\n }\n \n
    \n
    \n
    \n ) : (\n <>\n )}\n
    \n )}\n
    \n
    \n {feesHaveBeenModified() ? (\n
    \n {\n // check and see if we have an existing api call & clean it up before saving.\n if (calculateFeesPromiseRef.current) {\n await calculateFeesPromiseRef.current;\n }\n onSaveClick(feesRef.current);\n }}\n disabled={isReadOnly || errors.length > 0 || isAddingFeeOrSubtotal}\n data-testid={'save-fee-table-changes-data-testid'}\n />\n {\n // If the current state of the fees is different than the latest saved fees, prompt the user\n if (feesHaveBeenModified()) {\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: (): void => {\n setFees(initialFees);\n feesRef.current = cloneDeep(initialFees);\n discardCallback();\n setIsAddingFeeOrSubtotal(false);\n hideConfirmationOverlay();\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n }\n }}\n data-testid={'discard-fee-table-changes-data-testid'}\n />\n
    \n ) : (\n <>\n )}\n {errors && errors.length > 0 ? (\n
    \n {uniq(errors.map((error: FeeError) => error.message)).map((errorMessage) => {\n return (\n \n );\n })}\n
    \n ) : (\n <>\n )}\n
    \n
    \n
    \n );\n};\n\nexport default FeeTable;\n","import { CommandManagerService } from '../../../../../services/command/command-manager-service';\r\nimport { addCommandToBatchCommandObject } from '../../../../../utils/command-manager-service';\r\n\r\nconst feesReducer: DispatchManagerReducer<\r\n CommandManagerService,\r\n DispatchManagerDispatchActions_FeeMaintenance\r\n> = (\r\n dispatchData: CommandManagerService,\r\n action: DispatchManagerDispatchAction,\r\n): CommandManagerService => {\r\n switch (action.type) {\r\n case 'create-fee-definition':\r\n case 'delete-fee-definition':\r\n case 'update-fee-definition-name':\r\n case 'update-fee-definition-amount':\r\n case 'update-fee-definition-type':\r\n case 'update-fee-definition-order':\r\n return addCommandToBatchCommandObject(dispatchData, action.data as ICommand);\r\n\r\n default:\r\n return dispatchData;\r\n }\r\n};\r\n\r\nexport default feesReducer;\r\n","import { clone, isEqual, sortBy } from 'lodash';\r\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router';\r\nimport { FeesBatchCommand } from '../../../../classes/commands/fee-maintenace/batch-commands/fee-maintenace-batch-commands';\r\nimport { CreateFeeDefinitionCommand } from '../../../../classes/commands/fee-maintenace/commands/create-fee-definition-command';\r\nimport { DeleteFeeDefinitionCommand } from '../../../../classes/commands/fee-maintenace/commands/delete-fee-definition-command';\r\nimport { UpdateFeeDefinitionAmountCommand } from '../../../../classes/commands/fee-maintenace/commands/update-fee-definition-amount-command';\r\nimport { UpdateFeeDefinitionNameCommand } from '../../../../classes/commands/fee-maintenace/commands/update-fee-definition-name-command';\r\nimport { UpdateFeeDefinitionOrderCommand } from '../../../../classes/commands/fee-maintenace/commands/update-fee-definition-order-command';\r\nimport { UpdateFeeDefinitionFeeTypeCommand } from '../../../../classes/commands/fee-maintenace/commands/update-fee-definition-type-command';\r\nimport { FeeDefinition } from '../../../../classes/odata/fee-definition';\r\nimport GeneralConstants from '../../../../constants/general';\r\nimport ApplicationRoutes from '../../../../constants/routes';\r\nimport useCommandManagerDispatcher from '../../../../hooks/dispatch-manager-helper/useDispatcherWithCommandManagerService';\r\nimport { FeeApi, FrozenEntitiesApi } from '../../../../services';\r\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\r\nimport generateBatchCommandInitializerReducer from '../../../../services/command/reducers/command-manager-batch-command-initializer-reducer';\r\nimport commandManagerDispatchReducer from '../../../../services/command/reducers/command-manager-dispatch-reducer';\r\nimport { DispatchManagerContext } from '../../../../services/dispatch-manager/DispatchManager';\r\nimport { useLogger } from '../../../../services/logger/Logger';\r\nimport { convertFeeTypeToFeeTypeOption } from '../../../../utils/feeLabel';\r\nimport FeeTable, { DEFAULT_BID_TOTAL } from '../../../common-page-components/fee-table/FeeTable';\r\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\r\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\r\nimport useDegradedActionNotifications from '../../../shared-page-components/hooks/useDegradedActionNotifications';\r\nimport feesReducer from './reducers/fees';\r\n\r\n// The Group Id for the batching of fees commands\r\nconst feesDispatchKey = 'Fees-Group-Id';\r\n\r\nconst FeesPage: React.FC = () => {\r\n const { t } = useTranslation();\r\n const logger = useLogger();\r\n const history = useHistory();\r\n\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n const { showErrorNotification, showInfoNotification, showSuccessNotification } = useContext(\r\n NotificationPanelContext,\r\n );\r\n const { dispatchAction } = useContext(DispatchManagerContext);\r\n const [savedFees, setSavedFees] = useState();\r\n const [systemSettingEntityIsFrozen, setSystemSettingEntityIsFrozen] = useState(false);\r\n const userIsAdmin = AuthenticationService.currentUserInfo?.userIsAdmin() || false;\r\n\r\n // Initialize Command Manager Service\r\n const {\r\n initializeCommandManagerServiceOnDispatcher,\r\n commandManagerService,\r\n } = useCommandManagerDispatcher({ key: feesDispatchKey });\r\n\r\n useDegradedActionNotifications('FeesPage');\r\n\r\n // Register the dispatch key and reducer function with the Command Manager Service\r\n useEffect(() => {\r\n const batchCommandInitializerReducer = generateBatchCommandInitializerReducer(FeesBatchCommand);\r\n initializeCommandManagerServiceOnDispatcher(\r\n feesDispatchKey,\r\n batchCommandInitializerReducer,\r\n commandManagerDispatchReducer,\r\n feesReducer,\r\n );\r\n }, [initializeCommandManagerServiceOnDispatcher]);\r\n\r\n // Initial load of data\r\n useEffect(() => {\r\n const loadInitialData = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // NOTE: This page is not wired up to SignalR so we only perform this frozen entity check once on load\r\n const entityIsFrozen = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n );\r\n\r\n setSystemSettingEntityIsFrozen(entityIsFrozen);\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('general:pageLoadError'));\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n loadInitialData();\r\n }, [hidePageLoadingOverlay, history, logger, showErrorNotification, showPageLoadingOverlay, t]);\r\n\r\n //#region Converter Methods\r\n\r\n // convert the odata fees into the fees used by the page\r\n const convertToFeeDefinition = useCallback(\r\n (data: FeeDefinition): FeeDefinitionInfo => {\r\n return {\r\n id: data.id!,\r\n name: data.name!,\r\n order: data.order!,\r\n feeType: convertFeeTypeToFeeTypeOption(t, data.feeType!, data.referenceFeeName),\r\n amount: data.amount!,\r\n referenceFee: data.referenceFeeName,\r\n total: 0,\r\n isNew: false,\r\n };\r\n },\r\n [t],\r\n );\r\n\r\n // convert the odata fees into the fees used by the page\r\n const convertToFeeDTO = useCallback((data: FeeDefinitionInfo): FeeDTO => {\r\n return {\r\n name: data.name,\r\n order: data.order,\r\n feeType: data.feeType.value,\r\n amount: data.amount,\r\n referenceFeeName: data.referenceFee,\r\n value: data.total,\r\n };\r\n }, []);\r\n\r\n //#endregion\r\n\r\n //#region Hook Callbacks\r\n\r\n // Dispatch action to add a fee\r\n const addFeeCallback = useCallback(\r\n (fee: FeeDefinitionInfo) => {\r\n if (fee.feeType) {\r\n dispatchAction(feesDispatchKey, {\r\n data: new CreateFeeDefinitionCommand(fee.name.trim(), fee.feeType.value),\r\n type: 'create-fee-definition',\r\n });\r\n }\r\n },\r\n [dispatchAction],\r\n );\r\n\r\n // Dispatch action to delete a fee\r\n const deleteFeeCallback = useCallback(\r\n (fee: FeeDefinitionInfo) => {\r\n dispatchAction(feesDispatchKey, {\r\n data: new DeleteFeeDefinitionCommand(fee.name),\r\n type: 'delete-fee-definition',\r\n });\r\n },\r\n [dispatchAction],\r\n );\r\n\r\n // Dispatch action to update the name, amount, or type of a fee\r\n const updateFeeCallback = useCallback(\r\n (fee: FeeDefinitionInfo, updatedFee: FeeDefinitionInfo): void => {\r\n if (fee.name !== updatedFee.name) {\r\n dispatchAction(feesDispatchKey, {\r\n data: new UpdateFeeDefinitionNameCommand(fee.name, updatedFee.name.trim()),\r\n type: 'update-fee-definition-name',\r\n });\r\n }\r\n\r\n if (fee.amount !== updatedFee.amount) {\r\n dispatchAction(feesDispatchKey, {\r\n data: new UpdateFeeDefinitionAmountCommand(fee.name, updatedFee.amount),\r\n type: 'update-fee-definition-amount',\r\n });\r\n }\r\n\r\n // the type and the reference fee name should be changed together bc they are tied to one another when it relates to a percent fee type\r\n if (\r\n updatedFee.feeType &&\r\n (fee.feeType !== updatedFee.feeType || fee.referenceFee !== updatedFee.referenceFee)\r\n ) {\r\n dispatchAction(feesDispatchKey, {\r\n data: new UpdateFeeDefinitionFeeTypeCommand(\r\n fee.name,\r\n updatedFee.feeType.value,\r\n updatedFee.referenceFee,\r\n ),\r\n type: 'update-fee-definition-type',\r\n });\r\n }\r\n },\r\n [dispatchAction],\r\n );\r\n\r\n // Dispatch action on sort end to update the index of a fee\r\n const onSortEndCallback = useCallback(\r\n (previousFee: FeeDefinitionInfo, index: number) => {\r\n dispatchAction(feesDispatchKey, {\r\n data: new UpdateFeeDefinitionOrderCommand(previousFee.name, index),\r\n type: 'update-fee-definition-order',\r\n });\r\n },\r\n [dispatchAction],\r\n );\r\n\r\n const calculateFeesCallback = useCallback(\r\n async (feesToCalc: FeeDefinitionInfo[], baseCost: number): Promise => {\r\n try {\r\n // lets convert the fees to fee dtos\r\n const convertedFees = feesToCalc.map((f) => convertToFeeDTO(f));\r\n\r\n const calculateFeesDTO: CalculateFeesDTO = {\r\n fees: convertedFees,\r\n baseCost: baseCost,\r\n };\r\n\r\n const calculatedFees = await FeeApi.calculateFeesForGrid(calculateFeesDTO);\r\n\r\n // lets create a new list with the fees updated in necessary\r\n const updatedFees = feesToCalc.map((feeToCheck) => {\r\n //lets see if we can find the corresponding fee in the calculated fees\r\n const calculatedFee = calculatedFees.find((f) => f.name === feeToCheck.name);\r\n\r\n // if we a were able to find it and the calculated value has changed, lets create a new fee with the updated value.\r\n // Otherwise just return the existing fee as is.\r\n // we do this so that we are not changing the value of a fee that is stored in a state variable in the UI\r\n let feeToReturn = feeToCheck;\r\n\r\n if (calculatedFee && feeToCheck.total !== calculatedFee.value) {\r\n feeToReturn = clone(feeToCheck);\r\n feeToReturn.total = calculatedFee.value;\r\n }\r\n return feeToReturn;\r\n });\r\n return updatedFees;\r\n } catch (error) {\r\n logger.logError(error);\r\n\r\n // lets change the values to 0 so the user knows something is wrong. Either way the value never gets saved out anyways so no biggie\r\n const updatedFees = feesToCalc.map((feeToCheck) => {\r\n const feeToReturn = clone(feeToCheck);\r\n feeToReturn.total = 0;\r\n return feeToReturn;\r\n });\r\n\r\n showErrorNotification(t('general:error'), t('fees:calculationError'));\r\n return updatedFees;\r\n }\r\n },\r\n [convertToFeeDTO, showErrorNotification, t, logger],\r\n );\r\n\r\n //#endregion\r\n\r\n // variable indicating if we need to load the data from the api or use what's currently cached.\r\n const loadDataFromAPI = useRef(true);\r\n\r\n // after page render, load or refresh the data\r\n useEffect(() => {\r\n const loadFeesFromAPI = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // TODO we could optimize the calls so that when we call to ask for the fees, we could pass through a base cost to have it calculate the fees against so we dont have to call again to have the fees calculated.\r\n // We can worry about optimizations like that later if its necessary - MR\r\n let feesToSet = (await FeeApi.getFeeDefinitions()).map(convertToFeeDefinition);\r\n\r\n feesToSet = sortBy(feesToSet, (f) => f.order);\r\n\r\n // lets calculate the fees since we do not store the values\r\n feesToSet = await calculateFeesCallback(feesToSet, DEFAULT_BID_TOTAL);\r\n\r\n // Sets the collection we will use as comparison point to know if changes have been made when saving or discarding\r\n setSavedFees(feesToSet);\r\n // Update the flag so that we don't pull the data from the API, the next time useEffect is called.\r\n loadDataFromAPI.current = false;\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('fees:getFeesError'));\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n // if loadDataFromAPI is set to true then load the fees using the api data and set loadDataFromAPI to false; else, reload the data using cached/current values.\r\n if (loadDataFromAPI.current) {\r\n loadFeesFromAPI();\r\n }\r\n }, [\r\n showPageLoadingOverlay,\r\n hidePageLoadingOverlay,\r\n showErrorNotification,\r\n t,\r\n history,\r\n convertToFeeDefinition,\r\n calculateFeesCallback,\r\n logger,\r\n ]);\r\n\r\n const executeBatchCommands = useCallback(async (): Promise => {\r\n const commandManagerObj = commandManagerService;\r\n if (!commandManagerObj) {\r\n return;\r\n }\r\n\r\n // we need to create a deep copy of the command manager\r\n const newCommandManagerService = commandManagerObj.clone();\r\n const result = await newCommandManagerService.executeNextCommand();\r\n // If no command was present, null will be returned\r\n if (result === null) {\r\n return;\r\n }\r\n\r\n // Update the dispatch data since we just mutated the commands in the command manager\r\n dispatchAction(feesDispatchKey, {\r\n data: newCommandManagerService,\r\n type: 'update-command-manager',\r\n });\r\n }, [commandManagerService, dispatchAction]);\r\n\r\n const onSaveClick = useCallback(\r\n async (fees: FeeDefinitionInfo[]) => {\r\n try {\r\n if (isEqual(fees, savedFees)) {\r\n dispatchAction(feesDispatchKey, {\r\n data: null,\r\n type: 'clear-command-manager',\r\n });\r\n\r\n showInfoNotification(t('general:noChanges'), t('general:noChangesWereMade'));\r\n return;\r\n }\r\n\r\n showPageLoadingOverlay();\r\n await executeBatchCommands();\r\n setSavedFees(fees);\r\n showSuccessNotification(t('general:success'), t('fees:updateSuccess'));\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('fees:updateError'));\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n },\r\n [\r\n dispatchAction,\r\n executeBatchCommands,\r\n hidePageLoadingOverlay,\r\n savedFees,\r\n showErrorNotification,\r\n showInfoNotification,\r\n showPageLoadingOverlay,\r\n showSuccessNotification,\r\n t,\r\n logger,\r\n ],\r\n );\r\n\r\n const discardChanges = useCallback(() => {\r\n dispatchAction(feesDispatchKey, {\r\n data: null,\r\n type: 'clear-command-manager',\r\n });\r\n }, [dispatchAction]);\r\n\r\n return (\r\n
    \r\n {systemSettingEntityIsFrozen ? (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n \r\n
    \r\n\r\n {!savedFees ? (\r\n <>\r\n ) : (\r\n \r\n )}\r\n
    \r\n );\r\n};\r\n\r\nexport default FeesPage;\r\n","import { CommandBase } from '../../CommandBase';\n\nexport class CreateGeneralConditionsBidPackageDefinitionCommand extends CommandBase {\n public code: string;\n public description: string;\n\n constructor(code: string, description: string) {\n super(\n 'DESTINI.BidDay.Commands.BidDaySystem.CreateGeneralConditionsBidPackageDefinition',\n '',\n 'none',\n );\n this.code = code;\n this.description = description;\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateGeneralConditionsBidPackageDefinitionCodeCommand extends CommandBase {\n public code: string;\n public updatedCode: string;\n\n constructor(number: string, updatedNumber: string) {\n super(\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateGeneralConditionsBidPackageDefinitionCode',\n '',\n 'none',\n );\n this.code = number;\n this.updatedCode = updatedNumber;\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateGeneralConditionsBidPackageDefinitionDescriptionCommand extends CommandBase {\n public code: string;\n public description: string;\n public updatedDescription: string;\n\n constructor(code: string, description: string, updatedDescription: string) {\n super(\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateGeneralConditionsBidPackageDefinitionDescription',\n '',\n 'none',\n );\n this.code = code;\n this.description = description;\n this.updatedDescription = updatedDescription;\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class CreateBidPackageLineItemDefinitionCommand extends CommandBase {\n public bidPackageCode: string;\n public index: number;\n public description: string;\n public unitOfMeasure: string;\n\n constructor(bidPackageCode: string, index: number, description: string, unitOfMeasure: string) {\n super(' DESTINI.BidDay.Commands.BidDaySystem.CreateBidPackageLineItemDefinition', '', 'none');\n this.bidPackageCode = bidPackageCode;\n this.index = index;\n this.description = description;\n this.unitOfMeasure = unitOfMeasure;\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class DeleteBidPackageLineItemDefinitionCommand extends CommandBase {\n public bidPackageCode: string;\n public description: string;\n\n constructor(bidPackageCode: string, description: string) {\n super(' DESTINI.BidDay.Commands.BidDaySystem.DeleteBidPackageLineItemDefinition', '', 'none');\n this.bidPackageCode = bidPackageCode;\n this.description = description;\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateBidPackageLineItemDefinitionDescriptionCommand extends CommandBase {\n public bidPackageCode: string;\n public description: string;\n public updatedDescription: string;\n\n constructor(bidPackageCode: string, description: string, updatedDescription: string) {\n super(\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateBidPackageLineItemDefinitionDescription',\n '',\n 'none',\n );\n this.bidPackageCode = bidPackageCode;\n this.description = description;\n this.updatedDescription = updatedDescription;\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateBidPackageLineItemDefinitionIndexCommand extends CommandBase {\n public bidPackageCode: string;\n public description: string;\n public updatedIndex: number;\n\n constructor(bidPackageCode: string, description: string, updatedIndex: number) {\n super(\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateBidPackageLineItemDefinitionIndex',\n '',\n 'none',\n );\n this.bidPackageCode = bidPackageCode;\n this.description = description;\n this.updatedIndex = updatedIndex;\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateBidPackageLineItemDefinitionUnitOfMeasureCommand extends CommandBase {\n public bidPackageCode: string;\n public description: string;\n public unitOfMeasure: string;\n\n constructor(bidPackageCode: string, description: string, unitOfMeasure: string) {\n super(\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateBidPackageLineItemDefinitionUnitOfMeasure',\n '',\n 'none',\n );\n this.bidPackageCode = bidPackageCode;\n this.description = description;\n this.unitOfMeasure = unitOfMeasure;\n }\n}\n","import { CommandBatchBase } from '../../CommandBatchBase';\nimport { CreateGeneralConditionsBidPackageDefinitionCommand } from '../general-conditions-definitions/create-general-conditions-bid-package-definition-command';\nimport { UpdateGeneralConditionsBidPackageDefinitionCodeCommand } from '../general-conditions-definitions/update-general-conditions-bid-package-definition-code-command';\nimport { UpdateGeneralConditionsBidPackageDefinitionDescriptionCommand } from '../general-conditions-definitions/update-general-conditions-bid-package-definition-description';\nimport { CreateBidPackageLineItemDefinitionCommand } from '../line-item-definitions/create-bid-package-line-item-definition-command';\nimport { DeleteBidPackageLineItemDefinitionCommand } from '../line-item-definitions/delete-bid-package-line-item-definition-command';\nimport { UpdateBidPackageLineItemDefinitionDescriptionCommand } from '../line-item-definitions/update-bid-package-line-item-definition-description-command';\nimport { UpdateBidPackageLineItemDefinitionIndexCommand } from '../line-item-definitions/update-bid-package-line-item-definition-index-command';\nimport { UpdateBidPackageLineItemDefinitionUnitOfMeasureCommand } from '../line-item-definitions/update-bid-package-line-item-definition-unit-of-measure-command';\n\nexport class GeneralConditionsBatchCommand extends CommandBatchBase {\n constructor() {\n super('general-conditions-batch', '/bidDaySystemSettings', 'post', [\n CreateGeneralConditionsBidPackageDefinitionCommand,\n UpdateGeneralConditionsBidPackageDefinitionCodeCommand,\n UpdateGeneralConditionsBidPackageDefinitionDescriptionCommand,\n CreateBidPackageLineItemDefinitionCommand,\n DeleteBidPackageLineItemDefinitionCommand,\n UpdateBidPackageLineItemDefinitionDescriptionCommand,\n UpdateBidPackageLineItemDefinitionIndexCommand,\n UpdateBidPackageLineItemDefinitionUnitOfMeasureCommand,\n ]);\n }\n}\n","import { Form, Formik } from 'formik';\nimport React, { useCallback, useContext, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport * as Yup from 'yup';\nimport { UpdateGeneralConditionsBidPackageDefinitionCodeCommand } from '../../../../../classes/commands/general-conditions/general-conditions-definitions/update-general-conditions-bid-package-definition-code-command';\nimport { UpdateGeneralConditionsBidPackageDefinitionDescriptionCommand } from '../../../../../classes/commands/general-conditions/general-conditions-definitions/update-general-conditions-bid-package-definition-description';\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\nimport { DispatchManagerContext } from '../../../../../services/dispatch-manager/DispatchManager';\nimport { getFormErrorMessages } from '../../../../../utils/forms';\nimport { nameof } from '../../../../../utils/nameof';\nimport { areTrimmedStringsEqual } from '../../../../../utils/strings';\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\nimport FormErrorContainer from '../../../../common-page-components/forms/form-error-container/FormErrorContainer';\nimport FormFooter from '../../../../common-page-components/forms/FormFooter';\nimport FormTextInput from './../../../../common-page-components/forms/FormTextInput';\n\ninterface Props {\n generalConditionsDefinition: BidPackageDefinition;\n bidPackageDefinitions: BidPackageDefinition[];\n groupId: string;\n onSubmitClick: (bidPackageDefinition: BidPackageDefinition) => void;\n onDiscardClick: (bidPackageDefinition: BidPackageDefinition) => void;\n autoFocus?: boolean;\n}\n\nconst GeneralConditionsEditForm: React.FC = ({\n generalConditionsDefinition,\n bidPackageDefinitions,\n groupId,\n onSubmitClick,\n onDiscardClick,\n autoFocus,\n}) => {\n const { t } = useTranslation();\n\n const FormSchema = Yup.object().shape({\n id: Yup.string(),\n code: Yup.string()\n .trim()\n .max(\n EntityValidationConstants.GeneralConditionEntityLimits.Code_MaxLength,\n t('general-conditions:codeMaxLength', {\n maxLength: EntityValidationConstants.GeneralConditionEntityLimits.Code_MaxLength,\n }),\n )\n .required('General Conditions code is a required field'),\n description: Yup.string()\n .trim()\n .max(\n EntityValidationConstants.GeneralConditionEntityLimits.Description_MaxLength,\n t('general-conditions:descriptionMaxLength', {\n maxLength: EntityValidationConstants.GeneralConditionEntityLimits.Description_MaxLength,\n }),\n )\n .required('General Conditions description is a required field'),\n isNew: Yup.boolean(),\n });\n\n const { dispatchAction } = useContext(DispatchManagerContext);\n const [previousValidCode, setPreviousValidCode] = useState(\n generalConditionsDefinition.code,\n );\n\n // handles validating the code for the general conditions bid package\n const codeValidator = useCallback(\n (bidPackageCode: string): string | void => {\n if (areTrimmedStringsEqual(generalConditionsDefinition.code, bidPackageCode)) {\n return;\n }\n\n if (bidPackageDefinitions.find((b) => areTrimmedStringsEqual(b.code, bidPackageCode))) {\n return t('general-conditions:invalidGeneralConditionsCode') as string;\n }\n },\n [generalConditionsDefinition, bidPackageDefinitions, t],\n );\n\n // handles the Code editor losing focus tp allow us to dispatch the necessary command\n const handleCodeBlur = useCallback(\n (bidPackageCode: string): void => {\n //if wer are dealing with a new general conditions (bc one didnt exist before, )\n if (\n !generalConditionsDefinition.isNew &&\n !bidPackageDefinitions.find((b) => areTrimmedStringsEqual(b.code, bidPackageCode)) &&\n previousValidCode?.trim() !== bidPackageCode?.trim()\n ) {\n //TODO move this to the parent bc this editor form should not be repsonsible for adding the command\n // bc we only need to add the commands once, not potentially multiple times for every edit - MR\n dispatchAction(groupId, {\n data: new UpdateGeneralConditionsBidPackageDefinitionCodeCommand(\n previousValidCode,\n bidPackageCode.trim(),\n ),\n type: 'update-general-conditions-definition-code',\n });\n setPreviousValidCode(bidPackageCode);\n }\n },\n [\n generalConditionsDefinition,\n bidPackageDefinitions,\n dispatchAction,\n previousValidCode,\n groupId,\n ],\n );\n\n // handles the Description editor losing focus tp allow us to dispatch the necessary command\n const handleDescriptionBlur = useCallback(\n (description: string): void => {\n if (\n !generalConditionsDefinition.isNew &&\n generalConditionsDefinition.description?.trim() !== description?.trim()\n ) {\n //TODO move this to the parent bc this editor form should not be repsonsible for adding the command\n // bc we only need to add the commands once, not potentially multiple times for every edit - MR\n dispatchAction(groupId, {\n data: new UpdateGeneralConditionsBidPackageDefinitionDescriptionCommand(\n previousValidCode,\n generalConditionsDefinition.description,\n description.trim(),\n ),\n type: 'update-general-conditions-definition-description',\n });\n }\n },\n [dispatchAction, generalConditionsDefinition, groupId, previousValidCode],\n );\n\n // NOTE: With Formik, once we set the 'initialValues' property, updating it will not update the form values unless we set the 'enableReinitialize' flag\n // so we do not even render the Formik element unless the object we bind to its initial values is defined\n // NOTE: Related to TOUCHED\n // In order for Blur to cause the touched to be populated, the individual fields need to handle onBlur with the form's handleBlur handler\n // https://stackoverflow.com/questions/57385931/why-isnt-the-formik-touched-property-being-populated\n return (\n
    \n

    {t('general-conditions:editGeneralConditions')}

    \n\n {generalConditionsDefinition ? (\n \n {({ errors, values, submitCount, touched, handleBlur, setFieldValue }): JSX.Element => (\n
    \n {\n
    \n
    \n ) => {\n //lets trim the value of the code\n setFieldValue(nameof('code'), values.code?.trim());\n // must call the forms handler for blur to let the form know its been touched. see note above for more info\n handleBlur(event);\n handleCodeBlur(values.code);\n }}\n data-testid={'set-general-conditions-code-data-testid'}\n maxLength={\n EntityValidationConstants.GeneralConditionEntityLimits.Code_MaxLength\n }\n />\n
    \n
    \n ) => {\n //lets trim the value of the description\n setFieldValue(\n nameof('description'),\n values.description?.trim(),\n );\n // must call the forms handler for blur to let the form know its been touched. see note above for more info\n handleBlur(event);\n handleDescriptionBlur(values.description);\n }}\n data-testid={'set-general-conditions-description-data-testid'}\n maxLength={\n EntityValidationConstants.GeneralConditionEntityLimits.Description_MaxLength\n }\n />\n
    \n
    \n }\n\n \n
    \n 0}\n />\n {\n onDiscardClick(values);\n }}\n data-testid={'discard-general-conditions-definition-changes-data-testid'}\n disabled={values.isNew === true}\n />\n
    \n {submitCount > 0 || touched.code || touched.description ? (\n \n ) : (\n <> \n )}\n
    \n
    \n )}\n \n ) : (\n <>\n )}\n
    \n );\n};\n\nexport default GeneralConditionsEditForm;\n","import { DropDownListBlurEvent } from '@progress/kendo-react-dropdowns';\nimport { InputChangeEvent } from '@progress/kendo-react-inputs/dist/npm/input/interfaces/InputChangeEvent';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport GeneralConstants from '../../../../../constants/general';\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\nimport { nameof } from '../../../../../utils/nameof';\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\nimport BTIconButton from '../../../../common-page-components/controls/icon-button/BTIconButton';\nimport BTDropDownList, {\n BTDropDownListOption,\n} from '../../../../common-page-components/inputs/BTDropDownList';\nimport BTInput from '../../../../common-page-components/inputs/BTInput';\nimport './LineItemListItem.scss';\n\ninterface Props {\n errors: BidPackageLineItemDefinitionError[];\n isEditable: boolean;\n lineItemDefinition: BidPackageLineItemDefinition;\n availableUnitsOfMeasure: string[];\n addLineItemDefinition: (definition: BidPackageLineItemDefinition) => void;\n deleteLineItemDefinition: (definition: BidPackageLineItemDefinition) => void;\n updateLineItemDefinition_OnChange: (\n definition: BidPackageLineItemDefinition,\n updatedDefinition: BidPackageLineItemDefinition,\n isValid: boolean,\n ) => void;\n updateLineItemDefinition_OnBlur: (definitionId: string) => void;\n validateLineItemDefinition: (definition: BidPackageLineItemDefinition) => boolean;\n autoFocus?: boolean;\n}\n\nconst LineItemListItem: React.FC = ({\n errors,\n isEditable,\n lineItemDefinition,\n availableUnitsOfMeasure,\n addLineItemDefinition,\n deleteLineItemDefinition,\n updateLineItemDefinition_OnChange,\n updateLineItemDefinition_OnBlur,\n validateLineItemDefinition,\n autoFocus,\n}) => {\n const { t } = useTranslation();\n\n // holds the definition\n const [definitionToEdit, setDefinitionToEdit] = useState(\n lineItemDefinition,\n );\n const [validDefinition, setValidDefinition] = useState(\n lineItemDefinition,\n );\n\n // holds the filtered errors for this specific line item\n const [filteredErrors, setFilteredErrors] = useState([]);\n\n // holds the available unit of measure to select from for the given line item\n const [availableUnitOfMeasureListOptions, setAvailableUnitOfMeasureListOptions] = useState<\n BTDropDownListOption[]\n >([]);\n\n // When the errors have been udpated, lets filter out the errors specific for this line item\n useEffect(() => {\n setFilteredErrors(errors.filter((u) => u.id === definitionToEdit.id));\n }, [errors, definitionToEdit]);\n\n // anytime the line item definition has change in the parent, we need to set the definition being edited\n useEffect(() => {\n setDefinitionToEdit(lineItemDefinition);\n }, [lineItemDefinition]);\n\n // lets create the avilable drop down list options when the given units of measure have changed\n useEffect(() => {\n //let create the drop down list options from the MeasurementSystem enum\n setAvailableUnitOfMeasureListOptions(\n availableUnitsOfMeasure.map((c) => {\n return {\n name: c,\n value: c,\n };\n }),\n );\n }, [availableUnitsOfMeasure]);\n\n const addButtonClick = useCallback(() => {\n if (validateLineItemDefinition(definitionToEdit)) {\n addLineItemDefinition(definitionToEdit);\n }\n }, [validateLineItemDefinition, addLineItemDefinition, definitionToEdit]);\n\n const deleteButtonClick = useCallback(() => {\n deleteLineItemDefinition(definitionToEdit);\n }, [deleteLineItemDefinition, definitionToEdit]);\n\n const descriptionChangeHandler = useCallback(\n (event: InputChangeEvent) => {\n const updatedDefinition: BidPackageLineItemDefinition = {\n ...definitionToEdit,\n description: event.value,\n };\n // Set local definition state\n setDefinitionToEdit(updatedDefinition);\n\n const result = validateLineItemDefinition(updatedDefinition);\n\n // Check that the latest definition is valid and isn't new ('new' records are handled in addButtonClick())\n if (!definitionToEdit.isNew && result) {\n // Store the latest valid state in case the next entry is invalid and needs to be corrected\n setValidDefinition(updatedDefinition);\n updateLineItemDefinition_OnChange(definitionToEdit, updatedDefinition, result);\n }\n },\n [definitionToEdit, validateLineItemDefinition, updateLineItemDefinition_OnChange],\n );\n\n // handles the Description editor losing focus to allow validation of the field\n const descriptionBlurHandler = useCallback(() => {\n // intentionally check isNew first to short circuit validation\n // this is to prevent edge cases with new entries, but we want to validate existing entries.\n if (!definitionToEdit.isNew && validateLineItemDefinition(definitionToEdit)) {\n // update the line item definition in the parent\n updateLineItemDefinition_OnBlur(definitionToEdit.id);\n }\n }, [definitionToEdit, validateLineItemDefinition, updateLineItemDefinition_OnBlur]);\n\n const unitOfMeasureChangeHandler = useCallback(\n (newValue: unknown) => {\n const updatedDefinition: BidPackageLineItemDefinition = {\n ...definitionToEdit,\n unitOfMeasure: newValue as string,\n };\n // Set local definition state\n setDefinitionToEdit(updatedDefinition);\n\n //store off the validation result\n const result = validateLineItemDefinition(updatedDefinition);\n\n // Check that the latest definition is valid and isn't new ('new' records are handled in addButtonClick())\n if (!definitionToEdit.isNew) {\n // Update the parent component regardless of whether the line item is valid.\n updateLineItemDefinition_OnChange(validDefinition, updatedDefinition, result);\n\n //we only want to update the valid definition held here if...you guessed it...it is valid!\n if (result) {\n // Store the latest valid state in case the next entry is invalid and needs to be corrected\n setValidDefinition(updatedDefinition);\n }\n }\n },\n [\n definitionToEdit,\n updateLineItemDefinition_OnChange,\n validDefinition,\n validateLineItemDefinition,\n ],\n );\n\n // handles the unit of editor losing focus to allow validation of the field\n const unitOfMeasureBlurHandler = useCallback(\n (event: DropDownListBlurEvent) => {\n // we only want to allow validation on blur if this isnt the new item row.\n // If this is a new item, the change event should be the only way to validate, to not prevent the user from entering\n if (!definitionToEdit.isNew && validateLineItemDefinition(definitionToEdit)) {\n updateLineItemDefinition_OnBlur(definitionToEdit.id);\n }\n },\n [definitionToEdit, validateLineItemDefinition, updateLineItemDefinition_OnBlur],\n );\n\n // get any errors specific for a property of the line item definition\n const hasPropertySpecificErrors = useCallback(\n (property: string): boolean => {\n return filteredErrors.find((u) => u.property === property) !== undefined;\n },\n [filteredErrors],\n );\n\n return (\n
    \n
    \n {!isEditable ? (\n \n ) : (\n ('description'))\n ? 'fieldError'\n : ''\n }\n onChange={descriptionChangeHandler}\n onBlur={descriptionBlurHandler}\n disabled={!isEditable}\n autoFocus={autoFocus}\n maxLength={\n EntityValidationConstants.BidPackageLineItemEntityLimits.Description_MaxLength\n }\n onKeyDown={(e) => {\n if (\n e.key === GeneralConstants.KEY_ENTER &&\n (definitionToEdit.description || '').trim().length\n ) {\n addButtonClick();\n }\n }}\n />\n )}\n
    \n
    \n {!isEditable ? (\n \n ) : (\n ('unitOfMeasure'),\n )}\n disabled={!isEditable}\n displayValueIfNotInList={true}\n />\n )}\n
    \n {isEditable ? (\n definitionToEdit.isNew ? (\n
    \n
    \n {\n addButtonClick();\n }}\n disabled={\n errors.length > 0 ||\n !definitionToEdit?.description ||\n !definitionToEdit?.unitOfMeasure\n }\n />\n
    \n
    \n ) : (\n
    \n {\n deleteButtonClick();\n }}\n data-testid={'delete-line-item-definition-data-testid'}\n disabled={errors.length > 0}\n />\n
    \n )\n ) : (\n <>\n )}\n
    \n );\n};\n\nexport default LineItemListItem;\n","import { cloneDeep, sortBy, uniq } from 'lodash';\r\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Collapse } from 'reactstrap';\r\nimport { UnitOfMeasureApi } from '../../../../../services';\r\nimport { nameof } from '../../../../../utils/nameof';\r\nimport { generateUuid } from '../../../../../utils/uuid';\r\nimport { ConfirmationOverlayContext } from '../../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\r\nimport BTIconButton from '../../../../common-page-components/controls/icon-button/BTIconButton';\r\nimport BTSortableContainer, {\r\n BTSortableItem,\r\n} from '../../../../common-page-components/sortable/BTSortableContainer';\r\nimport GeneralConditionsEditForm from '../components/GeneralConditionsEditForm';\r\nimport LineItemListItem from '../components/LineItemListItem';\r\n\r\n// the return value from the hook\r\ninterface ReturnValue {\r\n generateGeneralConditionDetailsSection: (isReadOnly: boolean) => JSX.Element;\r\n generateGeneralConditionLineItemsSection: () => JSX.Element;\r\n setCurrentGeneralCondition: (definitions: BidPackageDefinition | undefined) => void;\r\n setExistingBidPackageDefinitions: (existingDefinitions: BidPackageDefinition[]) => void;\r\n initializeExistingLineItemDefinitions: (definitions: BidPackageLineItemDefinition[]) => void;\r\n}\r\n// The General Conditions hook\r\nconst useGeneralConditionContainer = (\r\n groupId: string,\r\n addLineItemDefinitionCallback: (definition: BidPackageLineItemDefinition) => void,\r\n deleteLineItemDefinitionCallback: (definition: BidPackageLineItemDefinition) => void,\r\n updateLineItemDefinitionCallback: (\r\n definition: BidPackageLineItemDefinition,\r\n updatedDefinition: BidPackageLineItemDefinition,\r\n ) => void,\r\n onSortEndCallback: (definition: BidPackageLineItemDefinition, index: number) => void,\r\n onSubmitClickCallback: (\r\n definition: BidPackageDefinition,\r\n // Bc the save/discard callback is passed in, it itself cannot contain call the setCurrentGeneralCondition method returned from the hook to set the general conditions.\r\n // For that reason, we must allow the ability to reset the container hook from within the callback through a parameter.\r\n // Is there probably a better way to do this?!? Probably, but this is good enough for now. 😬😊 - MR\r\n resetGeneralConditions: (definitions: BidPackageDefinition | undefined) => void,\r\n ) => void,\r\n onDiscardClickCallback: (\r\n definition: BidPackageDefinition,\r\n // same applies here as above - MR\r\n resetGeneralConditions: (definitions: BidPackageDefinition | undefined) => void,\r\n ) => void,\r\n): ReturnValue => {\r\n const { t } = useTranslation();\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n\r\n // --------------------Current Data--------------------\r\n\r\n //holds the current general condition definition\r\n const [generalConditionDefinition, setGeneralConditionDefinition] = useState<\r\n BidPackageDefinition | undefined\r\n >();\r\n\r\n // holds the general conditions definition to edit, if in edit mode\r\n const [generalConditionDefinitionToEdit, setGeneralConditionDefinitionToEdit] = useState<\r\n BidPackageDefinition | undefined\r\n >();\r\n\r\n //holds the current list of line item definitions within the general condition\r\n const [lineItemDefinitions, setLineItemDefinitions] = useState(\r\n [],\r\n );\r\n\r\n // maintain a copy of the definitions to generate commands on blur\r\n const definitionsCopy = useRef([]);\r\n\r\n // holds the available unit of measure to select from for the given line item\r\n const [availableUnitsOfMeasure, setAvailableUnitsOfMeasure] = useState([]);\r\n\r\n // holds the new line item definition to add, if in edit mode\r\n const [newLineItemDefinition, setNewLineItemDefinition] = useState<\r\n BidPackageLineItemDefinition | undefined\r\n >();\r\n\r\n // holds all of the existing bid packages that should be used to cpompare against for unique constraint(s)\r\n const [existingBidPackageDefinitions, setExistingBidPackageDefinitions] = useState<\r\n BidPackageDefinition[]\r\n >([]);\r\n\r\n // holds the flag for showing/hiding the editor for the general conditions details\r\n const [isGeneralConditionDetailsEditable, setIsGeneralConditionDetailsEditable] = useState<\r\n boolean\r\n >(false);\r\n\r\n // holds the flag for showing/hiding the editor for the general conditions line items\r\n const [isLineItemsEditable, setIsLineItemsEditable] = useState(false);\r\n\r\n // we must hold the errors bc the line item's UI is not using formik for validation\r\n const [lineItemErrors, setLineItemErrors] = useState([]);\r\n\r\n // Sets the current General Condition and Line Items being displayed/edited\r\n const setCurrentGeneralCondition = useCallback(\r\n (generalCondition: BidPackageDefinition | undefined): void => {\r\n //since the hook is being given a general condition to set, lets reset the the hook\r\n setGeneralConditionDefinitionToEdit(undefined);\r\n setNewLineItemDefinition(undefined);\r\n setLineItemErrors([]);\r\n setIsGeneralConditionDetailsEditable(false);\r\n setIsLineItemsEditable(false);\r\n\r\n setGeneralConditionDefinition(generalCondition);\r\n setLineItemDefinitions([...(generalCondition?.lineItemDefinitions ?? [])]);\r\n\r\n // if this is a new general conditions, we need to open up the editor so they can enter in a value and hit save\r\n if (generalCondition?.isNew) {\r\n setGeneralConditionDefinitionToEdit(generalCondition);\r\n setIsGeneralConditionDetailsEditable(true);\r\n }\r\n },\r\n [],\r\n );\r\n\r\n // updates the line item errors for a specific line item\r\n const updateLineItemErrors = useCallback(\r\n (id: string, errorMessages: BidPackageLineItemDefinitionError[]) => {\r\n // Remove old errors'\r\n let updatedErrors = lineItemErrors.filter((u) => u.id !== id);\r\n\r\n // Add new errors\r\n updatedErrors = updatedErrors.concat(errorMessages);\r\n\r\n setLineItemErrors(updatedErrors);\r\n },\r\n [lineItemErrors],\r\n );\r\n\r\n // creates a new definition for a new line item so that the user can added it\r\n const generateNewLineItemDefinition = useCallback((): BidPackageLineItemDefinition => {\r\n return {\r\n id: generateUuid(),\r\n bidPackageDefinitionId: generalConditionDefinition?.id ?? '',\r\n index: -1,\r\n description: '',\r\n unitOfMeasure: '',\r\n isNew: true,\r\n };\r\n }, [generalConditionDefinition]);\r\n\r\n // Lets get the latest units of measure when the line items can be edited\r\n useEffect(() => {\r\n if (isLineItemsEditable) {\r\n const loadUnitsOfMeasure = async (): Promise => {\r\n // Lets get the units of measure so we can save them.\r\n // Convert the objects to the string form. As a sanity, lets use empty string in case the name is undefined\r\n const unitsOfMeasure = (await UnitOfMeasureApi.getAllUnitsOfMeasure()).map(\r\n (uom) => uom.name ?? '',\r\n );\r\n //now lets sort the strings and set them as the available units of measure\r\n setAvailableUnitsOfMeasure(sortBy(unitsOfMeasure, (u) => u));\r\n };\r\n\r\n loadUnitsOfMeasure();\r\n }\r\n }, [isLineItemsEditable]);\r\n\r\n //loads the new line item definition if we are in editing mode\r\n useEffect(() => {\r\n if (isLineItemsEditable) {\r\n setNewLineItemDefinition(generateNewLineItemDefinition());\r\n }\r\n }, [isLineItemsEditable, generateNewLineItemDefinition]);\r\n\r\n // ----------------------------------------\r\n\r\n const addLineItemDefinition = useCallback(\r\n (definition: BidPackageLineItemDefinition): void => {\r\n let updatedDefinitions: BidPackageLineItemDefinition[] = [];\r\n\r\n definition.index = lineItemDefinitions?.length || 0;\r\n definition.isNew = false;\r\n updatedDefinitions = lineItemDefinitions\r\n ? [...lineItemDefinitions, definition]\r\n : [definition];\r\n\r\n setLineItemDefinitions(updatedDefinitions);\r\n definitionsCopy.current = cloneDeep(updatedDefinitions);\r\n\r\n // sanity check\r\n if (generalConditionDefinitionToEdit) {\r\n // cant forget to update the general conditions being edited\r\n setGeneralConditionDefinitionToEdit({\r\n ...generalConditionDefinitionToEdit,\r\n lineItemDefinitions: updatedDefinitions,\r\n });\r\n }\r\n addLineItemDefinitionCallback(definition);\r\n setNewLineItemDefinition(generateNewLineItemDefinition());\r\n },\r\n [\r\n lineItemDefinitions,\r\n addLineItemDefinitionCallback,\r\n generateNewLineItemDefinition,\r\n generalConditionDefinitionToEdit,\r\n ],\r\n );\r\n\r\n const initializeExistingLineItemDefinitions = useCallback(\r\n (definitions: BidPackageLineItemDefinition[]) => {\r\n setLineItemDefinitions(definitions);\r\n definitionsCopy.current = cloneDeep(definitions);\r\n },\r\n [setLineItemDefinitions],\r\n );\r\n\r\n const deleteLineItemDefinition = useCallback(\r\n (definition: BidPackageLineItemDefinition) => {\r\n let updatedDefinitions: BidPackageLineItemDefinition[] = [];\r\n if (lineItemDefinitions) {\r\n updatedDefinitions = [...lineItemDefinitions];\r\n }\r\n showConfirmationOverlay({\r\n text: t('general-conditions:confirmDelete', { description: definition.description }),\r\n buttons: [\r\n {\r\n text: t('general:yes'),\r\n onClick: (): void => {\r\n //Filter out the deleted definition\r\n updatedDefinitions = lineItemDefinitions\r\n ? lineItemDefinitions.filter((t) => t.description !== definition.description) || []\r\n : [];\r\n\r\n //Reset the index property based on the new collection\r\n if (lineItemDefinitions) {\r\n lineItemDefinitions.forEach((t, idx) => (t.index = idx));\r\n }\r\n\r\n setLineItemDefinitions(updatedDefinitions);\r\n definitionsCopy.current = cloneDeep(updatedDefinitions);\r\n\r\n const updatedErrors = lineItemErrors.filter((e) => e.id !== definition.id);\r\n setLineItemErrors(updatedErrors);\r\n\r\n // sanity check\r\n if (generalConditionDefinitionToEdit) {\r\n // cant forget to update the general conditions being edited\r\n setGeneralConditionDefinitionToEdit({\r\n ...generalConditionDefinitionToEdit,\r\n lineItemDefinitions: updatedDefinitions,\r\n });\r\n }\r\n\r\n //lets call the callback so that we can complete any additional action(s) necessary\r\n deleteLineItemDefinitionCallback(definition);\r\n\r\n hideConfirmationOverlay();\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:no'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n },\r\n [\r\n lineItemDefinitions,\r\n deleteLineItemDefinitionCallback,\r\n lineItemErrors,\r\n hideConfirmationOverlay,\r\n showConfirmationOverlay,\r\n t,\r\n generalConditionDefinitionToEdit,\r\n ],\r\n );\r\n\r\n const updateLineItemDefinition_OnChange = useCallback(\r\n (definition: BidPackageLineItemDefinition, updatedDefinition: BidPackageLineItemDefinition) => {\r\n let updatedDefinitions: BidPackageLineItemDefinition[] = [];\r\n if (lineItemDefinitions) {\r\n updatedDefinitions = [...lineItemDefinitions];\r\n }\r\n\r\n const index = lineItemDefinitions\r\n ? lineItemDefinitions.findIndex((t) => t.id === definition.id)\r\n : -1;\r\n updatedDefinitions.splice(index, 1, updatedDefinition);\r\n\r\n setLineItemDefinitions(updatedDefinitions);\r\n\r\n // sanity check\r\n if (generalConditionDefinitionToEdit) {\r\n // cant forget to update the general conditions being edited\r\n setGeneralConditionDefinitionToEdit({\r\n ...generalConditionDefinitionToEdit,\r\n lineItemDefinitions: updatedDefinitions,\r\n });\r\n }\r\n },\r\n [lineItemDefinitions, generalConditionDefinitionToEdit],\r\n );\r\n\r\n const updateLineItemDefinition_OnBlur = useCallback(\r\n (definitionId: string) => {\r\n const originalDefinition = definitionsCopy.current?.find((v) => v.id === definitionId);\r\n const updatedDefinition = lineItemDefinitions!.find((v) => v.id === definitionId);\r\n\r\n if (!originalDefinition || !updatedDefinition) {\r\n return;\r\n }\r\n\r\n updateLineItemDefinitionCallback(originalDefinition, updatedDefinition);\r\n definitionsCopy.current = cloneDeep(lineItemDefinitions);\r\n },\r\n [lineItemDefinitions, updateLineItemDefinitionCallback],\r\n );\r\n\r\n const validateLineItemDefinition = useCallback(\r\n (definition: BidPackageLineItemDefinition): boolean => {\r\n const duplicateDescriptionError = t('general-conditions:duplicateDescriptionError');\r\n const errorMessages: BidPackageLineItemDefinitionError[] = [];\r\n const description = definition.description ? definition.description.trim().toLowerCase() : '';\r\n const unitOfMeasure = definition.unitOfMeasure\r\n ? definition.unitOfMeasure.trim().toLowerCase()\r\n : '';\r\n\r\n // Check if the description is empty or whitespace\r\n if (!(description || '').length) {\r\n errorMessages.push({\r\n id: definition.id,\r\n property: nameof('description'),\r\n message: t('general-conditions:emptyDescriptionError'),\r\n });\r\n }\r\n\r\n // Map the descriptions, trimmed and converted to lower case to account for whitespace and different casings\r\n const descriptions: string[] = lineItemDefinitions\r\n ? lineItemDefinitions!.map((t) => (t.description ? t.description.trim().toLowerCase() : ''))\r\n : [];\r\n\r\n // Filter the modified descriptions to only look at values that appear more than once\r\n if (definition.isNew) {\r\n if (descriptions.indexOf(description) !== -1) {\r\n errorMessages.push({\r\n id: definition.id,\r\n property: nameof('description'),\r\n message: duplicateDescriptionError,\r\n });\r\n }\r\n } else {\r\n let duplicateDescriptions = [];\r\n duplicateDescriptions = descriptions.filter(\r\n (item, index) => item === description && index !== definition.index,\r\n );\r\n\r\n if (duplicateDescriptions.length > 0) {\r\n errorMessages.push({\r\n id: definition.id,\r\n property: nameof('description'),\r\n message: duplicateDescriptionError,\r\n });\r\n }\r\n }\r\n\r\n // Check if the unitOfMeasure is empty or whitespace\r\n if (!(unitOfMeasure || '').length) {\r\n errorMessages.push({\r\n id: definition.id,\r\n property: nameof('unitOfMeasure'),\r\n message: t('general-conditions:emptyUnitOfMeasureError'),\r\n });\r\n }\r\n\r\n updateLineItemErrors(definition.id, errorMessages);\r\n if (errorMessages.length > 0) {\r\n return false;\r\n }\r\n return true;\r\n },\r\n [lineItemDefinitions, updateLineItemErrors, t],\r\n );\r\n\r\n const onSubmitClick = useCallback(\r\n (definition: BidPackageDefinition) => {\r\n onSubmitClickCallback(definition, setCurrentGeneralCondition);\r\n },\r\n [onSubmitClickCallback, setCurrentGeneralCondition],\r\n );\r\n\r\n const onDiscardClick = useCallback(\r\n (definition: BidPackageDefinition) => {\r\n onDiscardClickCallback(definition, setCurrentGeneralCondition);\r\n },\r\n [onDiscardClickCallback, setCurrentGeneralCondition],\r\n );\r\n\r\n // --------------------UI Generation--------------------\r\n\r\n // Generates the UI for interacting with the Code and Description of the general conditions\r\n const generateGeneralConditionDetailsSection = useCallback(\r\n (isReadOnly: boolean): JSX.Element => {\r\n return (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n {generalConditionDefinitionToEdit ? (\r\n \r\n ) : (\r\n <> \r\n )}\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n {generalConditionDefinition ? (\r\n <>\r\n

    \r\n {`${generalConditionDefinition.code} - ${generalConditionDefinition.description}`}\r\n

    \r\n
    \r\n {\r\n setGeneralConditionDefinitionToEdit(generalConditionDefinition);\r\n setIsGeneralConditionDetailsEditable(true);\r\n }}\r\n //TODO still havent done tests yet, so will probably alter these or remove them once i make the test - MR\r\n data-testid={'edit-general-conditions-data-testid'}\r\n //bc the general conditions and line items are connected, you can only be editing one or the other, not both - MR\r\n disabled={\r\n isGeneralConditionDetailsEditable || isLineItemsEditable || isReadOnly\r\n }\r\n />\r\n {\r\n setGeneralConditionDefinitionToEdit(generalConditionDefinition);\r\n setIsLineItemsEditable(true);\r\n }}\r\n //TODO still havent done tests yet, so will probably alter these or remove them once i make the test - MR\r\n data-testid={'edit-line-items-data-testid'}\r\n //bc the general conditions and line items are connected, you can only be editing one or the other, not both - MR\r\n disabled={\r\n isGeneralConditionDetailsEditable || isLineItemsEditable || isReadOnly\r\n }\r\n />\r\n
    \r\n \r\n ) : (\r\n <> \r\n )}\r\n
    \r\n
    \r\n );\r\n },\r\n [\r\n isGeneralConditionDetailsEditable,\r\n generalConditionDefinition,\r\n generalConditionDefinitionToEdit,\r\n existingBidPackageDefinitions,\r\n isLineItemsEditable,\r\n onSubmitClick,\r\n onDiscardClick,\r\n t,\r\n groupId,\r\n ],\r\n );\r\n\r\n // Generates the UI for interacting with the Line Item Definitions of the current General Conditions\r\n const generateGeneralConditionLineItemsSection = useCallback((): JSX.Element => {\r\n // Maintains the state of the line items after the user has moved a definition\r\n const onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {\r\n if (lineItemDefinitions) {\r\n let updatedDefinitions = [...lineItemDefinitions];\r\n const previousDefinition = lineItemDefinitions[oldIndex];\r\n\r\n if (oldIndex < 0) {\r\n oldIndex += updatedDefinitions.length;\r\n }\r\n if (newIndex < 0) {\r\n newIndex += updatedDefinitions.length;\r\n }\r\n\r\n // lets first place the item into the correct index.\r\n updatedDefinitions.splice(newIndex, 0, updatedDefinitions.splice(oldIndex, 1)[0]);\r\n\r\n // now that they have been ordered correctly, lets update the indexes of the line items to match their order\r\n updatedDefinitions = updatedDefinitions.map((li, i) => {\r\n return {\r\n ...li,\r\n index: i,\r\n };\r\n });\r\n\r\n onSortEndCallback(previousDefinition, newIndex);\r\n setLineItemDefinitions(updatedDefinitions);\r\n definitionsCopy.current = cloneDeep(updatedDefinitions);\r\n\r\n // sanity check\r\n if (generalConditionDefinitionToEdit) {\r\n // cant forget to update the general conditions being edited\r\n setGeneralConditionDefinitionToEdit({\r\n ...generalConditionDefinitionToEdit,\r\n lineItemDefinitions: updatedDefinitions,\r\n });\r\n }\r\n }\r\n };\r\n\r\n // the generated line item elements to display to the user\r\n const generatedLineItemElements: BTSortableItem[] = lineItemDefinitions\r\n ? lineItemDefinitions.map((li) => {\r\n const item: BTSortableItem = {\r\n value: (\r\n \r\n ),\r\n key: li.id,\r\n };\r\n return item;\r\n })\r\n : [];\r\n return (\r\n
    \r\n \r\n {newLineItemDefinition ? (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n ) : (\r\n <> \r\n )}\r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n {\r\n if (generalConditionDefinitionToEdit) {\r\n onSubmitClick(generalConditionDefinitionToEdit);\r\n }\r\n }}\r\n disabled={lineItemErrors.length > 0}\r\n //TODO update test ids, if theyre even necessary - MR\r\n data-testid={'save-line-item-definition-changes-data-testid'}\r\n />\r\n {\r\n if (generalConditionDefinitionToEdit) {\r\n onDiscardClick(generalConditionDefinitionToEdit);\r\n }\r\n }}\r\n //TODO update test ids, if theyre even necessary - MR\r\n data-testid={'discard-line-item-definition-changes-data-testid'}\r\n />\r\n
    \r\n
    0 ? 'errorArea' : 'errorArea hidden'}>\r\n {lineItemErrors ? (\r\n uniq(\r\n lineItemErrors.map((error: BidPackageLineItemDefinitionError) => error.message),\r\n ).map((errorMessage) => {\r\n return (\r\n \r\n );\r\n })\r\n ) : (\r\n <> \r\n )}\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n );\r\n }, [\r\n lineItemDefinitions,\r\n isLineItemsEditable,\r\n newLineItemDefinition,\r\n lineItemErrors,\r\n availableUnitsOfMeasure,\r\n addLineItemDefinition,\r\n updateLineItemDefinition_OnBlur,\r\n updateLineItemDefinition_OnChange,\r\n deleteLineItemDefinition,\r\n validateLineItemDefinition,\r\n t,\r\n onSortEndCallback,\r\n generalConditionDefinitionToEdit,\r\n onSubmitClick,\r\n onDiscardClick,\r\n ]);\r\n\r\n return {\r\n generateGeneralConditionDetailsSection,\r\n generateGeneralConditionLineItemsSection,\r\n setCurrentGeneralCondition,\r\n setExistingBidPackageDefinitions,\r\n initializeExistingLineItemDefinitions,\r\n };\r\n};\r\n\r\nexport default useGeneralConditionContainer;\r\n","import { CommandManagerService } from '../../../../../services/command/command-manager-service';\nimport { addCommandToBatchCommandObject } from '../../../../../utils/command-manager-service';\n\nconst generalConditionsReducer: DispatchManagerReducer<\n CommandManagerService,\n DispatchManagerDispatchActions_GeneralConditions\n> = (\n dispatchData: CommandManagerService,\n action: DispatchManagerDispatchAction,\n): CommandManagerService => {\n switch (action.type) {\n case 'create-general-conditions-definition':\n case 'create-line-item-definition':\n case 'delete-line-item-definition':\n case 'update-general-conditions-definition-code':\n case 'update-general-conditions-definition-description':\n case 'update-line-item-definition-description':\n case 'update-line-item-definition-index':\n case 'update-line-item-definition-unit-of-measure':\n return addCommandToBatchCommandObject(dispatchData, action.data as ICommand);\n\n default:\n return dispatchData;\n }\n};\n\nexport default generalConditionsReducer;\n","import { isEqual, sortBy } from 'lodash';\r\nimport React, { useCallback, useContext, useEffect, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router';\r\nimport { GeneralConditionsBatchCommand } from '../../../../classes/commands/general-conditions/batch-commands/general-conditions-batch-command';\r\nimport { CreateGeneralConditionsBidPackageDefinitionCommand } from '../../../../classes/commands/general-conditions/general-conditions-definitions/create-general-conditions-bid-package-definition-command';\r\nimport { CreateBidPackageLineItemDefinitionCommand } from '../../../../classes/commands/general-conditions/line-item-definitions/create-bid-package-line-item-definition-command';\r\nimport { DeleteBidPackageLineItemDefinitionCommand } from '../../../../classes/commands/general-conditions/line-item-definitions/delete-bid-package-line-item-definition-command';\r\nimport { UpdateBidPackageLineItemDefinitionDescriptionCommand } from '../../../../classes/commands/general-conditions/line-item-definitions/update-bid-package-line-item-definition-description-command';\r\nimport { UpdateBidPackageLineItemDefinitionIndexCommand } from '../../../../classes/commands/general-conditions/line-item-definitions/update-bid-package-line-item-definition-index-command';\r\nimport { UpdateBidPackageLineItemDefinitionUnitOfMeasureCommand } from '../../../../classes/commands/general-conditions/line-item-definitions/update-bid-package-line-item-definition-unit-of-measure-command';\r\nimport GeneralConstants from '../../../../constants/general';\r\nimport ApplicationRoutes from '../../../../constants/routes';\r\nimport useCommandManagerDispatcher from '../../../../hooks/dispatch-manager-helper/useDispatcherWithCommandManagerService';\r\nimport { BidPackageMaintenanceApi, FrozenEntitiesApi } from '../../../../services';\r\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\r\nimport { CommandManagerService } from '../../../../services/command/command-manager-service';\r\nimport generateBatchCommandInitializerReducer from '../../../../services/command/reducers/command-manager-batch-command-initializer-reducer';\r\nimport commandManagerDispatchReducer from '../../../../services/command/reducers/command-manager-dispatch-reducer';\r\nimport { DispatchManagerContext } from '../../../../services/dispatch-manager/DispatchManager';\r\nimport { useLogger } from '../../../../services/logger/Logger';\r\nimport { addCommandToBatchCommandObject } from '../../../../utils/command-manager-service';\r\nimport { emptyUuid } from '../../../../utils/uuid';\r\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\r\nimport { BTGeneralContext } from '../../../common-page-components/general-contexts/BTGeneralContext';\r\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\r\nimport useDegradedActionNotifications from '../../../shared-page-components/hooks/useDegradedActionNotifications';\r\nimport './GeneralConditionsPage.scss';\r\nimport useGeneralConditionContainer from './hooks/useGeneralConditionContainer';\r\nimport generalConditionsReducer from './reducers/general-conditions-reducer';\r\n\r\nconst generalConditionsDispatchKey = 'General-Conditions-Group-Id';\r\n\r\nconst GeneralConditionsPage: React.FC = () => {\r\n const { t } = useTranslation();\r\n const logger = useLogger();\r\n const history = useHistory();\r\n\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n const { showSuccessNotification, showInfoNotification, showErrorNotification } = useContext(\r\n NotificationPanelContext,\r\n );\r\n const { dispatchAction } = useContext(DispatchManagerContext);\r\n const { setSystemSettings } = useContext(BTGeneralContext);\r\n\r\n const [systemSettingEntityIsFrozen, setSystemSettingEntityIsFrozen] = useState(false);\r\n const userIsAdmin = AuthenticationService.currentUserInfo?.userIsAdmin() ?? false;\r\n\r\n // Initialize Command Manager Service\r\n const {\r\n initializeCommandManagerServiceOnDispatcher,\r\n commandManagerService,\r\n } = useCommandManagerDispatcher({ key: generalConditionsDispatchKey });\r\n\r\n //the current general conditions\r\n const [generalConditionToEdit, setGeneralConditionToEdit] = useState<\r\n BidPackageDefinition | undefined\r\n >();\r\n\r\n useDegradedActionNotifications('GeneralConditionsPage');\r\n\r\n // Register preference group id and the necessary reducers with the Command Manager Service\r\n useEffect(() => {\r\n const batchCommandInitializerReducer = generateBatchCommandInitializerReducer(\r\n GeneralConditionsBatchCommand,\r\n );\r\n initializeCommandManagerServiceOnDispatcher(\r\n generalConditionsDispatchKey,\r\n batchCommandInitializerReducer,\r\n commandManagerDispatchReducer,\r\n generalConditionsReducer,\r\n );\r\n }, [initializeCommandManagerServiceOnDispatcher]);\r\n\r\n // Executes the general conditions batch command of the given command manager\r\n const executeBatchCommand = useCallback(\r\n async (commandManagerObj: CommandManagerService | undefined): Promise => {\r\n let success = false;\r\n if (!commandManagerObj) {\r\n return success;\r\n }\r\n\r\n // lets create a deep copy of the given command manager service\r\n const newCommandManagerService = commandManagerObj.clone();\r\n\r\n const result = await newCommandManagerService.executeNextCommand();\r\n // If no command was present, null will be returned\r\n if (result === null) {\r\n return success;\r\n }\r\n\r\n success = true;\r\n //TODO analyze the data in the response once we have decided what kind of data object we want to return when some errors are hit - MR\r\n\r\n // Update the dispatch data since we just mutated the commands in the command manager\r\n dispatchAction(generalConditionsDispatchKey, {\r\n data: newCommandManagerService,\r\n type: 'update-command-manager',\r\n });\r\n\r\n return success;\r\n },\r\n [dispatchAction],\r\n );\r\n\r\n const addLineItemDefinition = useCallback(\r\n (definition: BidPackageLineItemDefinition): void => {\r\n // sanity check\r\n if (!generalConditionToEdit) {\r\n return;\r\n }\r\n\r\n // dispatch the action\r\n dispatchAction(\r\n generalConditionsDispatchKey,\r\n {\r\n data: new CreateBidPackageLineItemDefinitionCommand(\r\n generalConditionToEdit.code,\r\n definition.index,\r\n definition.description.trim(),\r\n definition.unitOfMeasure,\r\n ),\r\n type: 'create-line-item-definition',\r\n },\r\n );\r\n },\r\n [generalConditionToEdit, dispatchAction],\r\n );\r\n\r\n const deleteLineItemDefinition = useCallback(\r\n (definition: BidPackageLineItemDefinition): void => {\r\n // sanity check\r\n if (!generalConditionToEdit) {\r\n return;\r\n }\r\n\r\n // dispatch the action\r\n dispatchAction(\r\n generalConditionsDispatchKey,\r\n {\r\n data: new DeleteBidPackageLineItemDefinitionCommand(\r\n generalConditionToEdit.code,\r\n definition.description,\r\n ),\r\n type: 'delete-line-item-definition',\r\n },\r\n );\r\n },\r\n [generalConditionToEdit, dispatchAction],\r\n );\r\n\r\n const updateLineItemDefinition = useCallback(\r\n (\r\n definition: BidPackageLineItemDefinition,\r\n updatedDefinition: BidPackageLineItemDefinition,\r\n ): void => {\r\n // sanity check\r\n if (!generalConditionToEdit) {\r\n return;\r\n }\r\n\r\n if (definition.description?.trim() !== updatedDefinition.description?.trim()) {\r\n dispatchAction(\r\n generalConditionsDispatchKey,\r\n {\r\n data: new UpdateBidPackageLineItemDefinitionDescriptionCommand(\r\n generalConditionToEdit.code,\r\n definition.description,\r\n updatedDefinition.description.trim(),\r\n ),\r\n type: 'update-line-item-definition-description',\r\n },\r\n );\r\n }\r\n\r\n if (definition.unitOfMeasure !== updatedDefinition.unitOfMeasure) {\r\n dispatchAction(\r\n generalConditionsDispatchKey,\r\n {\r\n data: new UpdateBidPackageLineItemDefinitionUnitOfMeasureCommand(\r\n generalConditionToEdit.code,\r\n definition.description,\r\n updatedDefinition.unitOfMeasure.trim(),\r\n ),\r\n type: 'update-line-item-definition-unit-of-measure',\r\n },\r\n );\r\n }\r\n },\r\n [generalConditionToEdit, dispatchAction],\r\n );\r\n\r\n const onSortEnd = useCallback(\r\n (previousDefinition: BidPackageLineItemDefinition, index: number) => {\r\n // sanity check\r\n if (!generalConditionToEdit) {\r\n return;\r\n }\r\n\r\n // dispatch the action\r\n dispatchAction(\r\n generalConditionsDispatchKey,\r\n {\r\n data: new UpdateBidPackageLineItemDefinitionIndexCommand(\r\n generalConditionToEdit.code,\r\n previousDefinition.description,\r\n index,\r\n ),\r\n type: 'update-line-item-definition-index',\r\n },\r\n );\r\n },\r\n [generalConditionToEdit, dispatchAction],\r\n );\r\n\r\n const onSubmitClick = useCallback(\r\n async (\r\n definition: BidPackageDefinition,\r\n resetGeneralConditions: (definitions: BidPackageDefinition | undefined) => void,\r\n ) => {\r\n // lets show the overlay to show that we are busy\r\n showPageLoadingOverlay();\r\n\r\n const isNewGeneralConditions = definition.isNew;\r\n try {\r\n //lets store off the command manager that we will send off to execute its batch command\r\n let commandManagerObj = commandManagerService;\r\n\r\n // we must handle the scenario where a general conditions does not exist yet.\r\n if (isNewGeneralConditions) {\r\n //lets make sure we have a command manager service\r\n if (commandManagerObj) {\r\n // Lets add this to the commands. There shouldn't be any other commands batched up, but to continue with the same paradigm, lets add this command.\r\n // Lets pass through the batch command class so it can be generated if one doesn't exist.\r\n commandManagerObj = addCommandToBatchCommandObject(\r\n commandManagerObj,\r\n new CreateGeneralConditionsBidPackageDefinitionCommand(\r\n definition.code.trim(),\r\n definition.description.trim(),\r\n ),\r\n GeneralConditionsBatchCommand,\r\n );\r\n } else {\r\n // if we got to this point, we are in a bad state, so lets throw an error so we know what happened\r\n throw new Error('Missing Command Manager Service');\r\n }\r\n } else if (isEqual(definition, generalConditionToEdit)) {\r\n // if the general conditions package is the same, then lets clear out the command manager and bounce out\r\n dispatchAction(\r\n generalConditionsDispatchKey,\r\n {\r\n data: null,\r\n type: 'clear-command-manager',\r\n },\r\n );\r\n showInfoNotification(t('general:noChanges'), t('general:noChangesWereMade'));\r\n resetGeneralConditions(generalConditionToEdit);\r\n return;\r\n }\r\n\r\n //lets execute any commands\r\n const result = await executeBatchCommand(commandManagerObj);\r\n\r\n if (result) {\r\n // if this was a new package, we need to create a copy to be able to properly set the IsNew property to false\r\n // otherwise just use the existing definition\r\n const definitionToSet = isNewGeneralConditions\r\n ? {\r\n ...definition,\r\n isNew: false,\r\n }\r\n : definition;\r\n\r\n setGeneralConditionToEdit(definitionToSet);\r\n resetGeneralConditions(definitionToSet);\r\n\r\n // Update the value in the shared general context\r\n setSystemSettings((currValue) => {\r\n return {\r\n ...currValue,\r\n generalConditionsCode: definitionToSet.code,\r\n canLoadSampleData: currValue?.canLoadSampleData ?? false,\r\n };\r\n });\r\n\r\n showSuccessNotification(\r\n t('general:success'),\r\n isNewGeneralConditions\r\n ? t('general-conditions:createGeneralConditionsSuccess')\r\n : t('general-conditions:updateGeneralConditionsSuccess'),\r\n );\r\n } else {\r\n showErrorNotification(\r\n t('general:error'),\r\n isNewGeneralConditions\r\n ? t('general-conditions:createGeneralConditionsError')\r\n : t('general-conditions:updateGeneralConditionsError'),\r\n );\r\n }\r\n } catch (error) {\r\n logger.logError(error);\r\n\r\n showErrorNotification(\r\n t('general:error'),\r\n isNewGeneralConditions\r\n ? t('general-conditions:createGeneralConditionsError')\r\n : t('general-conditions:updateGeneralConditionsError'),\r\n );\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n },\r\n [\r\n showPageLoadingOverlay,\r\n commandManagerService,\r\n generalConditionToEdit,\r\n executeBatchCommand,\r\n dispatchAction,\r\n showInfoNotification,\r\n t,\r\n setSystemSettings,\r\n showSuccessNotification,\r\n showErrorNotification,\r\n logger,\r\n history,\r\n hidePageLoadingOverlay,\r\n ],\r\n );\r\n\r\n const onDiscardClick = useCallback(\r\n (\r\n definition: BidPackageDefinition,\r\n resetGeneralConditions: (definitions: BidPackageDefinition | undefined) => void,\r\n ) => {\r\n const discardChanges = () => {\r\n dispatchAction(\r\n generalConditionsDispatchKey,\r\n {\r\n data: null,\r\n type: 'clear-command-manager',\r\n },\r\n );\r\n resetGeneralConditions(generalConditionToEdit);\r\n };\r\n\r\n // If the current state of the definitions is different than the latest saved definitions, prompt the user\r\n if (!isEqual(definition, generalConditionToEdit)) {\r\n showConfirmationOverlay({\r\n text: t('general:discardConfirmation'),\r\n buttons: [\r\n {\r\n text: t('general:discard'),\r\n onClick: (): void => {\r\n discardChanges();\r\n hideConfirmationOverlay();\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:cancel'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n } else {\r\n discardChanges();\r\n }\r\n },\r\n [dispatchAction, hideConfirmationOverlay, generalConditionToEdit, showConfirmationOverlay, t],\r\n );\r\n\r\n const {\r\n generateGeneralConditionDetailsSection,\r\n generateGeneralConditionLineItemsSection,\r\n setCurrentGeneralCondition,\r\n setExistingBidPackageDefinitions,\r\n initializeExistingLineItemDefinitions,\r\n } = useGeneralConditionContainer(\r\n generalConditionsDispatchKey,\r\n addLineItemDefinition,\r\n deleteLineItemDefinition,\r\n updateLineItemDefinition,\r\n onSortEnd,\r\n onSubmitClick,\r\n onDiscardClick,\r\n );\r\n\r\n // load the general conditions bid package from the query service\r\n useEffect(() => {\r\n const loadGeneralCondition = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // NOTE: This page is not wired up to SignalR so we only perform this frozen entity check once on load\r\n const entityIsFrozen = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n );\r\n\r\n setSystemSettingEntityIsFrozen(entityIsFrozen);\r\n\r\n let existingBidPackages = await BidPackageMaintenanceApi.getAllBidPackageDefinitions();\r\n\r\n existingBidPackages = sortBy(existingBidPackages, (b) => parseInt(b.code));\r\n setExistingBidPackageDefinitions(existingBidPackages);\r\n\r\n let generalConditions = await BidPackageMaintenanceApi.getGeneralConditionsDefinition();\r\n\r\n // We need to be able to handle the case where a general condition simply doesn't exist for whatever reason (hasn't been made yet, its been removed from the query, etc).\r\n if (!generalConditions) {\r\n // Lets create a new general conditions bid package.\r\n generalConditions = {\r\n id: emptyUuid,\r\n code: '00.00',\r\n description: 'General Conditions',\r\n tradeRequirementDefinitions: [],\r\n lineItemDefinitions: [],\r\n isNew: true,\r\n };\r\n } else {\r\n // since we were able to get the general conditions from the service, lets order the line items by their indexes\r\n generalConditions.lineItemDefinitions = sortBy(\r\n generalConditions.lineItemDefinitions,\r\n (t) => t.index,\r\n );\r\n }\r\n\r\n setGeneralConditionToEdit(generalConditions);\r\n setCurrentGeneralCondition(generalConditions);\r\n\r\n const lineItemDefinitions = generalConditions.lineItemDefinitions;\r\n if (lineItemDefinitions) {\r\n initializeExistingLineItemDefinitions(lineItemDefinitions);\r\n }\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('generalConditions:getGeneralConditionsError'));\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n loadGeneralCondition();\r\n }, [\r\n showPageLoadingOverlay,\r\n hidePageLoadingOverlay,\r\n showErrorNotification,\r\n t,\r\n history,\r\n setCurrentGeneralCondition,\r\n setExistingBidPackageDefinitions,\r\n initializeExistingLineItemDefinitions,\r\n logger,\r\n ]);\r\n\r\n return (\r\n <>\r\n
    \r\n {systemSettingEntityIsFrozen ? (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n {generateGeneralConditionDetailsSection(systemSettingEntityIsFrozen || !userIsAdmin)}\r\n
    \r\n
    {generateGeneralConditionLineItemsSection()}
    \r\n
    \r\n
    \r\n \r\n );\r\n};\r\n\r\nexport default GeneralConditionsPage;\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class CreateGeneralRequirementDefinitionCommand extends CommandBase {\r\n public index: number;\r\n public description: string;\r\n public requirementFulfillmentType: number;\r\n\r\n constructor(index: number, description: string, requirementFulfillmentType: number) {\r\n super('DESTINI.BidDay.Commands.BidDaySystem.CreateGeneralRequirementDefinition', '', 'none');\r\n this.index = index;\r\n this.description = description;\r\n this.requirementFulfillmentType = requirementFulfillmentType;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class DeleteGeneralRequirementDefinitionCommand extends CommandBase {\r\n public description: string;\r\n\r\n constructor(description: string) {\r\n super('DESTINI.BidDay.Commands.BidDaySystem.DeleteGeneralRequirementDefinition', '', 'none');\r\n this.description = description;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class UpdateGeneralRequirementDefinitionDescriptionCommand extends CommandBase {\r\n public description: string;\r\n public updatedDescription: string;\r\n\r\n constructor(description: string, updatedDescription: string) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateGeneralRequirementDefinitionDescription',\r\n '',\r\n 'none',\r\n );\r\n this.description = description;\r\n this.updatedDescription = updatedDescription;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class UpdateGeneralRequirementDefinitionIndexCommand extends CommandBase {\r\n public description: string;\r\n public updatedIndex: number;\r\n\r\n constructor(description: string, updatedIndex: number) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateGeneralRequirementDefinitionIndex',\r\n '',\r\n 'none',\r\n );\r\n this.description = description;\r\n this.updatedIndex = updatedIndex;\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\r\n\r\nexport class UpdateGeneralRequirementDefinitionRequirementFulfillmentTypeCommand extends CommandBase {\r\n public description: string;\r\n public requirementFulfillmentType: number;\r\n\r\n constructor(description: string, requirementFulfillmentType: number) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidDaySystem.UpdateGeneralRequirementDefinitionRequirementFulfillmentType',\r\n '',\r\n 'none',\r\n );\r\n this.description = description;\r\n this.requirementFulfillmentType = requirementFulfillmentType;\r\n }\r\n}\r\n","import { CommandBatchBase } from '../../CommandBatchBase';\r\nimport { CreateGeneralRequirementDefinitionCommand } from '../general-requirements-definitions/create-general-requirement-definition-command';\r\nimport { DeleteGeneralRequirementDefinitionCommand } from '../general-requirements-definitions/delete-general-requirement-definition-command';\r\nimport { UpdateGeneralRequirementDefinitionDescriptionCommand } from '../general-requirements-definitions/update-general-requirement-definition-description-command';\r\nimport { UpdateGeneralRequirementDefinitionIndexCommand } from '../general-requirements-definitions/update-general-requirement-definition-index-command';\r\nimport { UpdateGeneralRequirementDefinitionRequirementFulfillmentTypeCommand } from '../general-requirements-definitions/update-general-requirement-definition-requirement-fulfillment-type-command';\r\n\r\nexport class GeneralRequirementsBatchCommand extends CommandBatchBase {\r\n constructor() {\r\n super('general-requirements-batch', '/bidDaySystemSettings', 'post', [\r\n CreateGeneralRequirementDefinitionCommand,\r\n DeleteGeneralRequirementDefinitionCommand,\r\n UpdateGeneralRequirementDefinitionIndexCommand,\r\n UpdateGeneralRequirementDefinitionDescriptionCommand,\r\n UpdateGeneralRequirementDefinitionRequirementFulfillmentTypeCommand,\r\n ]);\r\n }\r\n}\r\n","const RequirementsConstants = {\r\n QUANTITATIVE: 'Contributes to Bid',\r\n QUALITATIVE: 'Yes/No',\r\n FREEFORM: 'Text',\r\n};\r\n\r\nexport default RequirementsConstants;\r\n","import { RadioGroupChangeEvent } from '@progress/kendo-react-inputs';\r\nimport { InputChangeEvent } from '@progress/kendo-react-inputs/dist/npm/input/interfaces/InputChangeEvent';\r\nimport React, { useCallback, useEffect, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport GeneralConstants from '../../../../../constants/general';\r\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\r\nimport RequirementsConstants from '../../../../../constants/requirements';\r\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\r\nimport BTIconButton from '../../../../common-page-components/controls/icon-button/BTIconButton';\r\nimport BTInput from '../../../../common-page-components/inputs/BTInput';\r\nimport BTRadioGroup, {\r\n BTRadioGroupOption,\r\n} from '../../../../common-page-components/inputs/BTRadioGroup';\r\nimport { RequirementFulfillmentTypes } from '../../../../enums/bid-package-enums';\r\nimport './RequirementListItem.scss';\r\n\r\ntype RequirementDefinitionType =\r\n | GeneralRequirementDefinitionInterface\r\n | TradeRequirementDefinitionInterface;\r\n\r\ninterface Props {\r\n errors: RequirementError[];\r\n hasErrors: boolean;\r\n isEditable: boolean;\r\n requirementDefinition: RequirementDefinitionType;\r\n autoFocus?: boolean;\r\n addRequirementDefinition: (definition: RequirementDefinitionType) => void;\r\n deleteRequirementDefinition: (definition: RequirementDefinitionType) => void;\r\n updateRequirementDefinition_OnChange: (\r\n definition: RequirementDefinitionType,\r\n updatedDefinition: RequirementDefinitionType,\r\n ) => void;\r\n updateRequirementDefinition_OnBlur: (definitionId: string) => void;\r\n updateRequirementFulfillmentType: (\r\n defintion: RequirementDefinitionType,\r\n updatedDefinition: RequirementDefinitionType,\r\n ) => void;\r\n validateRequirementDefinition: (definition: RequirementDefinitionType) => boolean;\r\n}\r\n\r\nconst radioButtonOptions: BTRadioGroupOption[] = [\r\n {\r\n label: RequirementsConstants.QUANTITATIVE,\r\n value: RequirementFulfillmentTypes.Quantitative,\r\n },\r\n {\r\n label: RequirementsConstants.QUALITATIVE,\r\n value: RequirementFulfillmentTypes.Qualitative,\r\n },\r\n {\r\n label: RequirementsConstants.FREEFORM,\r\n value: RequirementFulfillmentTypes.Freeform,\r\n },\r\n];\r\n\r\nconst RequirementsList: React.FC = ({\r\n errors,\r\n hasErrors,\r\n isEditable,\r\n requirementDefinition,\r\n autoFocus,\r\n addRequirementDefinition,\r\n deleteRequirementDefinition,\r\n updateRequirementDefinition_OnChange,\r\n updateRequirementDefinition_OnBlur,\r\n updateRequirementFulfillmentType,\r\n validateRequirementDefinition,\r\n}) => {\r\n const { t } = useTranslation();\r\n const [definitionToEdit, setDefinitionToEdit] = useState(\r\n requirementDefinition,\r\n );\r\n const [validDefinition, setValidDefinition] = useState(\r\n requirementDefinition,\r\n );\r\n\r\n // When the requirementDefinition prop is updated, overwrite existing changes with the new state\r\n useEffect(() => {\r\n if (!hasErrors && !definitionToEdit.isNew) {\r\n setDefinitionToEdit(requirementDefinition);\r\n }\r\n }, [requirementDefinition, hasErrors, definitionToEdit.isNew]);\r\n\r\n const addButtonClick = () => {\r\n if (validateRequirementDefinition(definitionToEdit)) {\r\n addRequirementDefinition(definitionToEdit);\r\n }\r\n };\r\n\r\n const deleteButtonClick = () => {\r\n deleteRequirementDefinition(definitionToEdit);\r\n };\r\n\r\n const descriptionChangeHandler = useCallback(\r\n (event: InputChangeEvent) => {\r\n const updatedDefinition: RequirementDefinitionType = {\r\n ...definitionToEdit,\r\n description: event.value,\r\n };\r\n // Set local definition state\r\n setDefinitionToEdit(updatedDefinition);\r\n // Check that the latest definition is valid and isn't new ('new' records are handled in addButtonClick())\r\n if (validateRequirementDefinition(updatedDefinition) && !definitionToEdit.isNew) {\r\n // Update the parent component\r\n updateRequirementDefinition_OnChange(validDefinition, updatedDefinition);\r\n // Store the latest valid state in case the next entry is invalid and needs to be corrected\r\n setValidDefinition(updatedDefinition);\r\n }\r\n },\r\n [\r\n definitionToEdit,\r\n updateRequirementDefinition_OnChange,\r\n validDefinition,\r\n validateRequirementDefinition,\r\n ],\r\n );\r\n\r\n const descriptionBlurHandler = useCallback(() => {\r\n // intentionally check isNew first to short circuit validation.\r\n // this is to prevent edge cases with new entries, but we want to validate existing entries\r\n if (!definitionToEdit.isNew && validateRequirementDefinition(definitionToEdit)) {\r\n // Update the parent component\r\n updateRequirementDefinition_OnBlur(definitionToEdit.id);\r\n }\r\n }, [definitionToEdit, updateRequirementDefinition_OnBlur, validateRequirementDefinition]);\r\n\r\n const requirementFulfillmentTypeChangeHandler = useCallback(\r\n (event: RadioGroupChangeEvent) => {\r\n const updatedDefinition: RequirementDefinitionType = {\r\n ...definitionToEdit,\r\n requirementFulfillmentType: event.value,\r\n };\r\n // Set local definition state\r\n setDefinitionToEdit(updatedDefinition);\r\n // Check that the latest definition isn't new ('new' records are handled in addButtonClick())\r\n if (!definitionToEdit.isNew) {\r\n // Update the parent component\r\n updateRequirementFulfillmentType(definitionToEdit, updatedDefinition);\r\n }\r\n },\r\n [definitionToEdit, updateRequirementFulfillmentType],\r\n );\r\n\r\n return (\r\n
    \r\n
    \r\n
    \r\n {!isEditable ? (\r\n \r\n ) : (\r\n 0)}\r\n autoFocus={autoFocus}\r\n maxLength={EntityValidationConstants.RequirementEntityLimits.Description_MaxLength}\r\n onKeyDown={(e) => {\r\n if (e.key === GeneralConstants.KEY_ENTER) {\r\n addButtonClick();\r\n }\r\n }}\r\n />\r\n )}\r\n
    \r\n
    \r\n 0}\r\n />\r\n
    \r\n\r\n {/* NOTE: We want to always show the column regardless if it has content */}\r\n
    \r\n
    \r\n {isEditable && !definitionToEdit.isNew ? (\r\n {\r\n deleteButtonClick();\r\n }}\r\n data-testid={'delete-requirement-definition-data-testid'}\r\n disabled={errors.length > 0}\r\n />\r\n ) : (\r\n <>\r\n )}\r\n
    \r\n
    \r\n\r\n {isEditable && definitionToEdit.isNew ? (\r\n
    \r\n
    \r\n {\r\n addButtonClick();\r\n }}\r\n disabled={errors.length > 0 || definitionToEdit.description === ''}\r\n />\r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n
    \r\n );\r\n};\r\n\r\nexport default RequirementsList;\r\n","import { cloneDeep } from 'lodash';\r\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Collapse } from 'reactstrap';\r\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\r\nimport { generateUuid } from '../../../../../utils/uuid';\r\nimport BTSortableContainer, {\r\n BTSortableItem,\r\n} from '../../../../common-page-components/sortable/BTSortableContainer';\r\nimport { RequirementFulfillmentTypes } from '../../../../enums/bid-package-enums';\r\nimport RequirementListItem from '../components/RequirementListItem';\r\n\r\ntype RequirementDefinitionType =\r\n | GeneralRequirementDefinitionInterface\r\n | TradeRequirementDefinitionInterface;\r\n\r\ninterface ReturnValue {\r\n requirementDefinitions: RequirementDefinitionType[];\r\n requirementErrors: RequirementError[];\r\n generateAddGeneralRequirementDefinitionRow: () => JSX.Element;\r\n generateAddTradeRequirementDefinitionRow: () => JSX.Element;\r\n generateRequirementList: (\r\n requirementDefinitions: RequirementDefinitionType[],\r\n requirementErrors: RequirementError[],\r\n ) => JSX.Element;\r\n setRequirementDefinitions: (definitions: RequirementDefinitionType[]) => void;\r\n setRequirementErrors: (errors: RequirementError[]) => void;\r\n}\r\n\r\nconst useRequirementList = (\r\n isEditable: boolean,\r\n addRequirementDefinitionCallback: (definition: RequirementDefinitionType) => void,\r\n deleteRequirementDefinitionCallback: (definition: RequirementDefinitionType) => void,\r\n updateRequirementDefinitionCallback: (\r\n definition: RequirementDefinitionType,\r\n updatedDefinition: RequirementDefinitionType,\r\n ) => void,\r\n onSortEndCallback: (definition: RequirementDefinitionType, index: number) => void,\r\n): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const [definitions, setDefinitions] = useState([]);\r\n // We maintain a copy of the definitions that we use to generate commands on blur\r\n const definitionsCopy = useRef([]);\r\n\r\n const [errors, setErrors] = useState([]);\r\n\r\n //Handles generation and seeding of new General Requirement Defininitions\r\n const [newGeneralRequirementDefinition, setNewGeneralRequirementDefinition] = useState<\r\n GeneralRequirementDefinitionInterface\r\n >();\r\n const generateNewGeneralRequirementDefinition = useCallback((): GeneralRequirementDefinitionInterface => {\r\n return {\r\n id: generateUuid(),\r\n index: -1,\r\n description: '',\r\n requirementFulfillmentType: RequirementFulfillmentTypes.Qualitative,\r\n isNew: true,\r\n };\r\n }, []);\r\n\r\n //Handles generation and seeding of new Trade Requirement Defininitions\r\n const [newTradeRequirementDefinition, setNewTradeRequirementDefinition] = useState<\r\n TradeRequirementDefinitionInterface\r\n >();\r\n const generateNewTradeRequirementDefinition = useCallback((): TradeRequirementDefinitionInterface => {\r\n return {\r\n id: generateUuid(),\r\n index: -1,\r\n description: '',\r\n requirementFulfillmentType: RequirementFulfillmentTypes.Qualitative,\r\n isNew: true,\r\n };\r\n }, []);\r\n\r\n const duplicateDescriptionError = t('bid-package-maintenance:duplicateDescriptionError');\r\n const emptyDescriptionError = t('bid-package-maintenance:emptyDescriptionError');\r\n\r\n useEffect(() => {\r\n if (isEditable) {\r\n setNewGeneralRequirementDefinition(generateNewGeneralRequirementDefinition());\r\n setNewTradeRequirementDefinition(generateNewTradeRequirementDefinition());\r\n }\r\n }, [generateNewGeneralRequirementDefinition, generateNewTradeRequirementDefinition, isEditable]);\r\n\r\n const addRequirementDefinition = useCallback(\r\n (definition: RequirementDefinitionType): void => {\r\n let updatedDefinitions: RequirementDefinitionType[] = [];\r\n\r\n definition.index = definitions?.length || 0;\r\n definition.isNew = false;\r\n updatedDefinitions = definitions ? [...definitions, definition] : [definition];\r\n\r\n setDefinitions(updatedDefinitions);\r\n definitionsCopy.current = cloneDeep(updatedDefinitions);\r\n\r\n addRequirementDefinitionCallback(definition);\r\n setNewGeneralRequirementDefinition(generateNewGeneralRequirementDefinition());\r\n },\r\n [addRequirementDefinitionCallback, definitions, generateNewGeneralRequirementDefinition],\r\n );\r\n\r\n const deleteRequirementDefinition = useCallback(\r\n (definition: RequirementDefinitionType) => {\r\n let updatedDefinitions: RequirementDefinitionType[] = [];\r\n if (definitions) {\r\n updatedDefinitions = [...definitions];\r\n }\r\n //Filter out the deleted definition\r\n updatedDefinitions = definitions\r\n ? definitions.filter((t) => t.description !== definition.description) || []\r\n : [];\r\n\r\n //Reset the index property based on the new collection\r\n if (definitions) {\r\n definitions.forEach((t, idx) => (t.index = idx));\r\n }\r\n\r\n setDefinitions(updatedDefinitions);\r\n definitionsCopy.current = cloneDeep(updatedDefinitions);\r\n\r\n const updatedErrors = errors.filter((e) => e.id !== definition.id);\r\n setErrors(updatedErrors);\r\n deleteRequirementDefinitionCallback(definition);\r\n },\r\n [definitions, deleteRequirementDefinitionCallback, errors],\r\n );\r\n\r\n const updateRequirementDefinition_OnChange = useCallback(\r\n (definition: RequirementDefinitionType, updatedDefinition: RequirementDefinitionType) => {\r\n let updatedDefinitions: RequirementDefinitionType[] = [];\r\n if (definitions) {\r\n updatedDefinitions = [...definitions];\r\n }\r\n\r\n const index = definitions ? definitions.findIndex((t) => t.id === definition.id) : -1;\r\n updatedDefinitions.splice(index, 1, updatedDefinition);\r\n\r\n setDefinitions(updatedDefinitions);\r\n },\r\n [definitions],\r\n );\r\n\r\n const updateRequirementDefinition_OnBlur = useCallback(\r\n (definitionId: string) => {\r\n const originalDefinition = definitionsCopy.current?.find((v) => v.id === definitionId);\r\n const updatedDefinition = definitions!.find((v) => v.id === definitionId);\r\n\r\n if (!originalDefinition || !updatedDefinition) {\r\n return;\r\n }\r\n\r\n updateRequirementDefinitionCallback(originalDefinition, updatedDefinition);\r\n definitionsCopy.current = cloneDeep(definitions);\r\n },\r\n [definitions, updateRequirementDefinitionCallback],\r\n );\r\n\r\n const updateRequirementFulfillmentType = useCallback(\r\n (definition: RequirementDefinitionType, updatedDefinition: RequirementDefinitionType) => {\r\n let updatedDefinitions: RequirementDefinitionType[] = [];\r\n if (definitions) {\r\n updatedDefinitions = [...definitions];\r\n }\r\n\r\n const index = definitions ? definitions.findIndex((t) => t.id === definition.id) : -1;\r\n updatedDefinitions.splice(index, 1, updatedDefinition);\r\n\r\n setDefinitions(updatedDefinitions);\r\n updateRequirementDefinitionCallback(definition, updatedDefinition);\r\n definitionsCopy.current = cloneDeep(definitions);\r\n },\r\n [definitions, updateRequirementDefinitionCallback],\r\n );\r\n\r\n const setRequirementDefinitions = useCallback(\r\n (definitions: RequirementDefinitionType[]): void => {\r\n setDefinitions(definitions);\r\n definitionsCopy.current = cloneDeep(definitions);\r\n },\r\n [],\r\n );\r\n\r\n const setRequirementErrors = useCallback(\r\n (id: string, errorMessages: string[]): RequirementError[] => {\r\n // Remove old errors'\r\n let updatedErrors = errors.filter((u) => u.id !== id);\r\n\r\n // Add new errors\r\n updatedErrors = updatedErrors.concat(\r\n errorMessages.map((e) => {\r\n return { id: id, message: e };\r\n }),\r\n );\r\n\r\n setErrors(updatedErrors);\r\n return updatedErrors;\r\n },\r\n [errors],\r\n );\r\n\r\n const validateRequirementDefinition = useCallback(\r\n (definition: RequirementDefinitionType): boolean => {\r\n const errorMessages: string[] = [];\r\n const description = definition.description ? definition.description.trim().toLowerCase() : '';\r\n\r\n // Check if the description is empty or whitespace\r\n if (!(description || '').length) {\r\n errorMessages.push(emptyDescriptionError);\r\n }\r\n\r\n // Check if the description is longer than the max length\r\n if (\r\n description.length > EntityValidationConstants.RequirementEntityLimits.Description_MaxLength\r\n ) {\r\n errorMessages.push(\r\n t('general-requirements:requirementDescriptionMaxLength', {\r\n maxLength: EntityValidationConstants.RequirementEntityLimits.Description_MaxLength,\r\n }),\r\n );\r\n }\r\n\r\n // Map the descriptions, trimmed and converted to lower case to account for whitespace and different casings\r\n const descriptions: string[] = definitions\r\n ? definitions!.map((t) => (t.description ? t.description.trim().toLowerCase() : ''))\r\n : [];\r\n\r\n // Filter the modified descriptions to only look at values that appear more than once\r\n if (definition.isNew) {\r\n if (descriptions.indexOf(description) !== -1) {\r\n errorMessages.push(duplicateDescriptionError);\r\n }\r\n } else {\r\n let duplicateDescriptions = [];\r\n duplicateDescriptions = descriptions.filter(\r\n (item, index) => item === description && index !== definition.index,\r\n );\r\n\r\n if (duplicateDescriptions.length > 0) {\r\n errorMessages.push(duplicateDescriptionError);\r\n }\r\n }\r\n\r\n setRequirementErrors(definition.id, errorMessages);\r\n if (errorMessages.length > 0) {\r\n return false;\r\n }\r\n return true;\r\n },\r\n [definitions, duplicateDescriptionError, emptyDescriptionError, setRequirementErrors, t],\r\n );\r\n\r\n const definitionHasErrors = useCallback(\r\n (id: string): boolean => {\r\n return errors.find((e) => e.id === id) !== undefined;\r\n },\r\n [errors],\r\n );\r\n\r\n const generateRequirementList = useCallback(\r\n (\r\n requirementDefinitions: RequirementDefinitionType[],\r\n requirementErrors: RequirementError[],\r\n ): JSX.Element => {\r\n // Maintains the state of the requirementDefinitions after the user has moved a definition\r\n const onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {\r\n if (requirementDefinitions) {\r\n const updatedDefinitions = [...requirementDefinitions];\r\n const previousDefinition = requirementDefinitions[oldIndex];\r\n\r\n if (oldIndex < 0) {\r\n oldIndex += updatedDefinitions.length;\r\n }\r\n if (newIndex < 0) {\r\n newIndex += updatedDefinitions.length;\r\n }\r\n updatedDefinitions.splice(newIndex, 0, updatedDefinitions.splice(oldIndex, 1)[0]);\r\n onSortEndCallback(previousDefinition, newIndex);\r\n\r\n setDefinitions(updatedDefinitions);\r\n definitionsCopy.current = cloneDeep(updatedDefinitions);\r\n }\r\n };\r\n\r\n const generatedRequirementList: BTSortableItem[] = requirementDefinitions\r\n ? requirementDefinitions.map((definition: RequirementDefinitionType) => {\r\n const item: BTSortableItem = {\r\n value: (\r\n \r\n ),\r\n key: definition.id,\r\n };\r\n return item;\r\n })\r\n : [];\r\n\r\n return (\r\n \r\n );\r\n },\r\n [\r\n addRequirementDefinition,\r\n definitionHasErrors,\r\n deleteRequirementDefinition,\r\n isEditable,\r\n onSortEndCallback,\r\n updateRequirementDefinition_OnBlur,\r\n updateRequirementDefinition_OnChange,\r\n updateRequirementFulfillmentType,\r\n validateRequirementDefinition,\r\n ],\r\n );\r\n\r\n const generateAddGeneralRequirementDefinitionRow = useCallback((): JSX.Element => {\r\n return (\r\n \r\n {newGeneralRequirementDefinition && (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n )}\r\n
    \r\n );\r\n }, [\r\n addRequirementDefinition,\r\n definitionHasErrors,\r\n deleteRequirementDefinition,\r\n errors,\r\n isEditable,\r\n newGeneralRequirementDefinition,\r\n updateRequirementDefinition_OnBlur,\r\n updateRequirementDefinition_OnChange,\r\n updateRequirementFulfillmentType,\r\n validateRequirementDefinition,\r\n ]);\r\n\r\n const generateAddTradeRequirementDefinitionRow = useCallback((): JSX.Element => {\r\n return (\r\n \r\n {newTradeRequirementDefinition && (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n )}\r\n
    \r\n );\r\n }, [\r\n addRequirementDefinition,\r\n definitionHasErrors,\r\n deleteRequirementDefinition,\r\n errors,\r\n isEditable,\r\n newTradeRequirementDefinition,\r\n updateRequirementDefinition_OnBlur,\r\n updateRequirementDefinition_OnChange,\r\n updateRequirementFulfillmentType,\r\n validateRequirementDefinition,\r\n ]);\r\n\r\n return {\r\n requirementDefinitions: definitions,\r\n requirementErrors: errors,\r\n generateAddGeneralRequirementDefinitionRow,\r\n generateAddTradeRequirementDefinitionRow,\r\n generateRequirementList,\r\n setRequirementDefinitions: setRequirementDefinitions,\r\n setRequirementErrors: setErrors,\r\n };\r\n};\r\n\r\nexport default useRequirementList;\r\n","import { CommandManagerService } from '../../../../../services/command/command-manager-service';\r\nimport { addCommandToBatchCommandObject } from '../../../../../utils/command-manager-service';\r\n\r\nconst generalRequirementsReducer: DispatchManagerReducer<\r\n CommandManagerService,\r\n DispatchManagerDispatchActions_GeneralRequirements\r\n> = (\r\n dispatchData: CommandManagerService,\r\n action: DispatchManagerDispatchAction,\r\n): CommandManagerService => {\r\n switch (action.type) {\r\n case 'create-general-requirement-definition':\r\n case 'delete-general-requirement-definition':\r\n case 'update-general-requirement-definition-description':\r\n case 'update-general-requirement-definition-index':\r\n case 'update-general-requirement-definition-requirement-fulfillment-type':\r\n return addCommandToBatchCommandObject(dispatchData, action.data as ICommand);\r\n\r\n default:\r\n return dispatchData;\r\n }\r\n};\r\n\r\nexport default generalRequirementsReducer;\r\n","import { isEqual, sortBy, uniq } from 'lodash';\r\nimport React, { useCallback, useContext, useEffect, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router-dom';\r\nimport { CreateGeneralRequirementDefinitionCommand } from '../../../../classes/commands/general-requirements/general-requirements-definitions/create-general-requirement-definition-command';\r\nimport { DeleteGeneralRequirementDefinitionCommand } from '../../../../classes/commands/general-requirements/general-requirements-definitions/delete-general-requirement-definition-command';\r\nimport { UpdateGeneralRequirementDefinitionDescriptionCommand } from '../../../../classes/commands/general-requirements/general-requirements-definitions/update-general-requirement-definition-description-command';\r\nimport { UpdateGeneralRequirementDefinitionIndexCommand } from '../../../../classes/commands/general-requirements/general-requirements-definitions/update-general-requirement-definition-index-command';\r\nimport { UpdateGeneralRequirementDefinitionRequirementFulfillmentTypeCommand } from '../../../../classes/commands/general-requirements/general-requirements-definitions/update-general-requirement-definition-requirement-fulfillment-type-command';\r\nimport GeneralConstants from '../../../../constants/general';\r\nimport ApplicationRoutes from '../../../../constants/routes';\r\nimport useCommandManagerDispatcher from '../../../../hooks/dispatch-manager-helper/useDispatcherWithCommandManagerService';\r\nimport { FrozenEntitiesApi, GeneralRequirementsApi } from '../../../../services';\r\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\r\nimport generateBatchCommandInitializerReducer from '../../../../services/command/reducers/command-manager-batch-command-initializer-reducer';\r\nimport commandManagerDispatchReducer from '../../../../services/command/reducers/command-manager-dispatch-reducer';\r\nimport { DispatchManagerContext } from '../../../../services/dispatch-manager/DispatchManager';\r\nimport { useLogger } from '../../../../services/logger/Logger';\r\nimport { NotificationService } from '../../../../services/notification/notification-service';\r\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport BTButton from '../../../common-page-components/controls/button/BTButton';\r\nimport BTFloatingIconButton from '../../../common-page-components/controls/floating-icon-button/BTFloatingIconButton';\r\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\r\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\r\nimport useDegradedActionNotifications from '../../../shared-page-components/hooks/useDegradedActionNotifications';\r\nimport { GeneralRequirementsBatchCommand } from './../../../../classes/commands/general-requirements/batch-commands/general-requirements-batch-commands';\r\nimport './GeneralRequirementsPage.scss';\r\nimport useRequirementList from './hooks/useRequirementList';\r\nimport generalRequirementsReducer from './reducers/general-requirement-reducer';\r\n\r\nconst generalRequirementsDispatchKey = 'General-Requirements-Group-Id';\r\n\r\nconst GeneralRequirementsPage: React.FC = () => {\r\n const { t } = useTranslation();\r\n const logger = useLogger();\r\n const history = useHistory();\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n\r\n // lets store the timeout so we can clear it out properly so the page loading overlay isn't cleared out unnecessary due to the timeout\r\n const [timeoutForPageLoadingOverlay, setTimeoutForPageLoadingOverlay] = useState<\r\n NodeJS.Timeout\r\n >();\r\n\r\n const { showErrorNotification, showInfoNotification, showSuccessNotification } = useContext(\r\n NotificationPanelContext,\r\n );\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n const [savedGeneralRequirementDefinitions, setSavedGeneralRequirementDefinitions] = useState<\r\n GeneralRequirementDefinitionInterface[]\r\n >([]);\r\n\r\n const { dispatchAction } = useContext(DispatchManagerContext);\r\n const [isEditable, setIsEditable] = useState(false);\r\n\r\n const [systemSettingEntityIsFrozen, setSystemSettingEntityIsFrozen] = useState(false);\r\n const userIsAdmin = AuthenticationService.currentUserInfo?.userIsAdmin() ?? false;\r\n\r\n // Initialize Command Manager Service\r\n const {\r\n initializeCommandManagerServiceOnDispatcher,\r\n commandManagerService,\r\n } = useCommandManagerDispatcher({ key: generalRequirementsDispatchKey });\r\n\r\n useDegradedActionNotifications('GeneralRequirementsPage');\r\n\r\n // Whenever a command is completed for the current user, clear out the page loading overlay\r\n useEffect(() => {\r\n NotificationService.onAllEventsForCommandProcessed((message) => {\r\n logger.logDebug('GeneralRequirementsPage.onAllEventsForCommandProcessed', message);\r\n\r\n // lets only clear out the timeout loading overlay if we currently have a timeout for the page loading overlay\r\n if (timeoutForPageLoadingOverlay) {\r\n clearTimeout(timeoutForPageLoadingOverlay);\r\n setTimeoutForPageLoadingOverlay(undefined);\r\n }\r\n\r\n // lets show that we completed the update successfully\r\n showSuccessNotification(t('general:success'), t('general-requirements:updateSuccess'));\r\n //let hide the data once all of the commands have been processed\r\n hidePageLoadingOverlay();\r\n });\r\n\r\n return function cleanup() {\r\n NotificationService.offAllEventsForCommandProcessed();\r\n };\r\n }, [hidePageLoadingOverlay, timeoutForPageLoadingOverlay, showSuccessNotification, t, logger]);\r\n\r\n // Register groupId and reducer function with the Command Manager Service\r\n useEffect(() => {\r\n const batchCommandInitializerReducer = generateBatchCommandInitializerReducer(\r\n GeneralRequirementsBatchCommand,\r\n );\r\n initializeCommandManagerServiceOnDispatcher(\r\n generalRequirementsDispatchKey,\r\n batchCommandInitializerReducer,\r\n commandManagerDispatchReducer,\r\n generalRequirementsReducer,\r\n );\r\n }, [initializeCommandManagerServiceOnDispatcher]);\r\n\r\n const executeBatchCommands = useCallback(async (): Promise => {\r\n let success = false;\r\n const commandManagerObj = commandManagerService;\r\n if (!commandManagerObj) {\r\n return success;\r\n }\r\n\r\n // we need to create a deep copy of the command manager\r\n const newCommandManagerService = commandManagerObj.clone();\r\n const result = await newCommandManagerService.executeNextCommand();\r\n\r\n // If no command was present, null will be returned\r\n if (result === null) {\r\n return success;\r\n }\r\n success = true;\r\n\r\n // Update the dispatch data since we just mutated the commands in the command manager\r\n dispatchAction(generalRequirementsDispatchKey, {\r\n data: newCommandManagerService,\r\n type: 'update-command-manager',\r\n });\r\n return success;\r\n }, [commandManagerService, dispatchAction]);\r\n\r\n const addGeneralRequirementDefinition = useCallback(\r\n (definition: GeneralRequirementDefinitionInterface): void => {\r\n dispatchAction(\r\n generalRequirementsDispatchKey,\r\n {\r\n data: new CreateGeneralRequirementDefinitionCommand(\r\n definition.index,\r\n definition.description.trim(),\r\n definition.requirementFulfillmentType,\r\n ),\r\n type: 'create-general-requirement-definition',\r\n },\r\n );\r\n },\r\n [dispatchAction],\r\n );\r\n\r\n const deleteGeneralRequirementDefinition = useCallback(\r\n (definition: GeneralRequirementDefinitionInterface): void => {\r\n dispatchAction(\r\n generalRequirementsDispatchKey,\r\n {\r\n data: new DeleteGeneralRequirementDefinitionCommand(definition.description),\r\n type: 'delete-general-requirement-definition',\r\n },\r\n );\r\n },\r\n [dispatchAction],\r\n );\r\n\r\n const updateGeneralRequirementDefinition = useCallback(\r\n (\r\n definition: GeneralRequirementDefinitionInterface,\r\n updatedDefinition: GeneralRequirementDefinitionInterface,\r\n ): void => {\r\n if (definition.description !== updatedDefinition.description) {\r\n dispatchAction(\r\n generalRequirementsDispatchKey,\r\n {\r\n data: new UpdateGeneralRequirementDefinitionDescriptionCommand(\r\n definition.description,\r\n updatedDefinition.description.trim(),\r\n ),\r\n type: 'update-general-requirement-definition-description',\r\n },\r\n );\r\n }\r\n\r\n if (definition.requirementFulfillmentType !== updatedDefinition.requirementFulfillmentType) {\r\n dispatchAction(\r\n generalRequirementsDispatchKey,\r\n {\r\n data: new UpdateGeneralRequirementDefinitionRequirementFulfillmentTypeCommand(\r\n definition.description,\r\n updatedDefinition.requirementFulfillmentType,\r\n ),\r\n type: 'update-general-requirement-definition-requirement-fulfillment-type',\r\n },\r\n );\r\n }\r\n },\r\n [dispatchAction],\r\n );\r\n\r\n const onSortEnd = useCallback(\r\n (previousDefinition: GeneralRequirementDefinitionInterface, index: number) => {\r\n dispatchAction(\r\n generalRequirementsDispatchKey,\r\n {\r\n data: new UpdateGeneralRequirementDefinitionIndexCommand(\r\n previousDefinition.description,\r\n index,\r\n ),\r\n type: 'update-general-requirement-definition-index',\r\n },\r\n );\r\n },\r\n [dispatchAction],\r\n );\r\n\r\n const {\r\n requirementDefinitions,\r\n requirementErrors,\r\n generateAddGeneralRequirementDefinitionRow,\r\n generateRequirementList,\r\n setRequirementDefinitions,\r\n setRequirementErrors,\r\n } = useRequirementList(\r\n isEditable,\r\n addGeneralRequirementDefinition,\r\n deleteGeneralRequirementDefinition,\r\n updateGeneralRequirementDefinition,\r\n onSortEnd,\r\n );\r\n\r\n // Initial load of data\r\n useEffect(() => {\r\n const loadGeneralRequirementDefinitions = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // NOTE: This page is not wired up to SignalR so we only perform this frozen entity check once on load\r\n const entityIsFrozen = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n );\r\n\r\n setSystemSettingEntityIsFrozen(entityIsFrozen);\r\n\r\n let definitions: GeneralRequirementDefinitionInterface[] = await GeneralRequirementsApi.getAllGeneralRequirementDefinitions();\r\n definitions = sortBy(definitions, (t) => t.index);\r\n\r\n // Sets the initial definitions managed in the useRequirementListing hook\r\n setRequirementDefinitions(definitions);\r\n\r\n // Sets the fallback definitions used when discarding changes\r\n setSavedGeneralRequirementDefinitions(definitions);\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('general:pageLoadError'));\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n loadGeneralRequirementDefinitions();\r\n }, [\r\n hidePageLoadingOverlay,\r\n history,\r\n setRequirementDefinitions,\r\n showErrorNotification,\r\n showPageLoadingOverlay,\r\n t,\r\n logger,\r\n ]);\r\n\r\n const discardChanges = useCallback(() => {\r\n dispatchAction(generalRequirementsDispatchKey, {\r\n data: null,\r\n type: 'clear-command-manager',\r\n });\r\n setRequirementDefinitions(savedGeneralRequirementDefinitions);\r\n setRequirementErrors([]);\r\n setIsEditable(false);\r\n }, [\r\n dispatchAction,\r\n savedGeneralRequirementDefinitions,\r\n setRequirementDefinitions,\r\n setRequirementErrors,\r\n ]);\r\n\r\n const onDiscardClick = useCallback(() => {\r\n // If the current state of the definitions is different than the latest saved definitions, prompt the user\r\n if (\r\n !isEqual(requirementDefinitions, savedGeneralRequirementDefinitions) ||\r\n requirementErrors.length > 0\r\n ) {\r\n showConfirmationOverlay({\r\n text: t('general:discardConfirmation'),\r\n buttons: [\r\n {\r\n text: t('general:discard'),\r\n onClick: (): void => {\r\n discardChanges();\r\n hideConfirmationOverlay();\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:cancel'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n } else {\r\n setIsEditable(false);\r\n }\r\n }, [\r\n discardChanges,\r\n hideConfirmationOverlay,\r\n requirementDefinitions,\r\n requirementErrors.length,\r\n savedGeneralRequirementDefinitions,\r\n showConfirmationOverlay,\r\n t,\r\n ]);\r\n\r\n const onSaveClick = useCallback(async () => {\r\n try {\r\n if (isEqual(requirementDefinitions, savedGeneralRequirementDefinitions)) {\r\n dispatchAction(\r\n generalRequirementsDispatchKey,\r\n {\r\n data: null,\r\n type: 'clear-command-manager',\r\n },\r\n );\r\n\r\n showInfoNotification(t('general:noChanges'), t('general:noChangesWereMade'));\r\n setIsEditable(false);\r\n return;\r\n }\r\n showPageLoadingOverlay();\r\n const result = await executeBatchCommands();\r\n if (result) {\r\n // lets clear out the page loading overlay using a timeout in case we don't get a response from signal r.\r\n // we also want to make sure we clear out the timeout properly so store off the timeout to prevent the page loading overlay from being cleared out unnecessarily\r\n setTimeoutForPageLoadingOverlay(\r\n setTimeout(() => {\r\n // although we haven't received an update from signal, that doesn't mean we didn't successfully send off the command to update the general requirements\r\n showSuccessNotification(t('general:success'), t('general-requirements:updateSuccess'));\r\n hidePageLoadingOverlay();\r\n }, GeneralConstants.SIGNALR_WAIT_TIMEOUT),\r\n );\r\n setSavedGeneralRequirementDefinitions(requirementDefinitions);\r\n setIsEditable(false);\r\n } else {\r\n showErrorNotification(\r\n t('general:error'),\r\n t('general-requirements:requirementsUpdateError'),\r\n );\r\n //lets hide the page loading overlay if we couldn't successfully execute the batch command\r\n hidePageLoadingOverlay();\r\n }\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('general-requirements:requirementsUpdateError'));\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n hidePageLoadingOverlay();\r\n }\r\n }, [\r\n dispatchAction,\r\n executeBatchCommands,\r\n hidePageLoadingOverlay,\r\n requirementDefinitions,\r\n savedGeneralRequirementDefinitions,\r\n showErrorNotification,\r\n showInfoNotification,\r\n showPageLoadingOverlay,\r\n showSuccessNotification,\r\n t,\r\n history,\r\n logger,\r\n ]);\r\n\r\n return (\r\n
    \r\n {systemSettingEntityIsFrozen ? (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n \r\n
    \r\n
    {generateAddGeneralRequirementDefinitionRow()}
    \r\n\r\n
    \r\n {requirementDefinitions && requirementDefinitions.length > 0 ? (\r\n <>\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n {generateRequirementList(requirementDefinitions, requirementErrors)}\r\n \r\n ) : (\r\n
    \r\n {t('general-requirements:noGeneralRequirementsFound')}\r\n
    \r\n )}\r\n
    \r\n {isEditable && (\r\n
    \r\n
    \r\n
    \r\n {\r\n onSaveClick();\r\n }}\r\n data-testid={'save-general-requirement-definition-changes-data-testid'}\r\n disabled={\r\n systemSettingEntityIsFrozen || requirementErrors.length > 0 || !userIsAdmin\r\n }\r\n />\r\n {\r\n onDiscardClick();\r\n }}\r\n data-testid={'discard-general-requirement-definition-changes-data-testid'}\r\n disabled={systemSettingEntityIsFrozen || !userIsAdmin}\r\n />\r\n
    \r\n
    0 ? 'errorArea' : 'errorArea hidden'}>\r\n {requirementErrors &&\r\n uniq(requirementErrors.map((error: RequirementError) => error.message)).map(\r\n (errorMessage) => {\r\n return (\r\n \r\n );\r\n },\r\n )}\r\n
    \r\n
    \r\n
    \r\n )}\r\n\r\n {\r\n setIsEditable(!isEditable);\r\n }}\r\n disabled={isEditable || systemSettingEntityIsFrozen || !userIsAdmin}\r\n />\r\n
    \r\n );\r\n};\r\n\r\nexport default GeneralRequirementsPage;\r\n","import { CommandBase } from '../CommandBase';\n\nexport class UpdateMeasurementSystemCommand extends CommandBase {\n public measurementSystem: number;\n\n constructor(measurementSystem: number) {\n super('DESTINI.BidDay.Commands.BidDaySystem.UpdateMeasurementSystem', '', 'none');\n\n this.measurementSystem = measurementSystem;\n }\n}\n","import { CommandBase } from '../CommandBase';\n\nexport class UpdateBiddersRangesCommand extends CommandBase {\n public lowBiddersMax: number;\n public midBiddersMax: number;\n\n constructor(lowBiddersMax: number, midBiddersMax: number) {\n super('DESTINI.BidDay.Commands.Application.UpdateBiddersRanges', '', 'none');\n\n this.lowBiddersMax = lowBiddersMax;\n this.midBiddersMax = midBiddersMax;\n }\n}\n","import { CommandBatchBase } from '../../CommandBatchBase';\nimport { UpdateMeasurementSystemCommand } from '../update-measurement-system-command';\nimport { UpdateBiddersRangesCommand } from '../update-bidders-ranges-command';\n\nexport class PreferencesBatchCommand extends CommandBatchBase {\n constructor() {\n super('Preferences', '/preferences', 'put', [\n UpdateMeasurementSystemCommand,\n UpdateBiddersRangesCommand,\n ]);\n }\n}\n","import React from 'react';\r\nimport { NumericTextBox } from '@progress/kendo-react-inputs';\r\nimport { Field, FieldProps } from 'formik';\r\nimport { get } from 'lodash';\r\nimport './Forms.scss';\r\nimport { NumberFormatOptions } from '@progress/kendo-react-intl';\r\n\r\ninterface Props {\r\n label: string;\r\n name: string;\r\n id?: string;\r\n min?: number;\r\n max?: number;\r\n tabIndex?: number;\r\n validator?: (value: string) => string | void;\r\n format?: string | NumberFormatOptions;\r\n disabled?: boolean;\r\n}\r\n\r\nconst WrappedNumericTextInput: React.FC = ({ field, form, label, ...rest }) => {\r\n const errors = get(form.errors, field.name);\r\n const hasErrors = !!errors;\r\n\r\n const classNames = ['formInput'];\r\n if (hasErrors && form.submitCount) {\r\n classNames.push('formInputError');\r\n }\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst FormNumericTextInput: React.FC = (props) => {\r\n return (\r\n
    \r\n \r\n
    \r\n );\r\n};\r\n\r\nexport default FormNumericTextInput;\r\n","import { connect, Form, Formik, FormikProps } from 'formik';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport * as Yup from 'yup';\nimport MeasurementSystems from '../../../../../constants/preferences';\nimport { getFormErrorMessages } from '../../../../../utils/forms';\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\nimport FormErrorContainer from '../../../../common-page-components/forms/form-error-container/FormErrorContainer';\nimport FormFooter from '../../../../common-page-components/forms/FormFooter';\nimport FormNumericTextInput from '../../../../common-page-components/forms/FormNumericTextInput';\nimport BTInput from '../../../../common-page-components/inputs/BTInput';\nimport './../../../../../styles/bidders-ranges-container.scss';\n\ninterface Props {\n preferences: Preferences;\n onSubmitClick: (preferences: Preferences) => void;\n onDiscardClick: (preferences: Preferences) => void;\n isReadOnly: boolean;\n}\n\nconst PreferencesEditForm: React.FC = (props) => {\n const { t } = useTranslation();\n\n const FormSchema = Yup.object().shape({\n measurementSystem: Yup.object()\n .typeError(t('preferences:measurementSystemRequired'))\n .required(t('preferences:measurementSystemRequired'))\n .shape({\n id: Yup.number()\n .typeError(t('preferences:measurementSystemRequired'))\n .required(t('preferences:measurementSystemRequired'))\n .oneOf(Object.values(MeasurementSystems).map((v) => v.id)),\n name: Yup.string().required(t('preferences:measurementSystemRequired')),\n }),\n lowBiddersMax: Yup.number()\n .integer(t('preferences:lowRangeMaxWholeNumber'))\n .typeError(t('preferences:lowRangeMaxRequired'))\n .min(0, t('preferences:lowRangeMaxAtLeastZero'))\n .max(1000, t('preferences:lowRangeMaxAtMostOneThousand'))\n .required(t('preferences:lowRangeMaxRequired')),\n midBiddersMax: Yup.number()\n .integer(t('preferences:midRangeMaxWholeNumber'))\n .typeError(t('preferences:midRangeMaxRequired'))\n .min(\n typeof Yup.ref('lowBiddersMax') === 'number' ? Number(Yup.ref('lowBiddersMax')) + 1 : 1,\n t('preferences:midRangeMaxGreaterThanLowRangeMax'),\n ) //this is so that we can have a low range.\n .max(1000, t('preferences:midRangeMaxAtMostOneThousand'))\n .required(t('preferences:midRangeMaxRequired')),\n });\n\n // const getAvailableMeasurementSystems = (): FormDropDownListOption[] => {\n // //let create the drop down list options from the MeasurementSystem enum\n // return MeasurementSystems.map((c) => {\n // return {\n // name: t(`preferences:${c.name.toLowerCase()}`),\n // value: c,\n // };\n // });\n // };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const FormikEffect = connect((props: any) => {\n props.onFormChanged(props.formik);\n return null;\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onFormChanged = (form: FormikProps): void => {\n if (form && form.values) {\n const formPreferences = form.values as Preferences;\n\n //the only time we need to auto adjust a range is when the low (red) bidders range pushes into the mid (yellow) bidders range and vice versa.\n //At that point, we need to make sure the mid(yellow) bidders range is +1 of the low(red) bidders max.\n if (formPreferences && formPreferences.lowBiddersMax >= formPreferences.midBiddersMax) {\n //add one to the mid max to allow for the mid range to be valid\n const newMidMax = formPreferences.lowBiddersMax + 1;\n if (formPreferences.midBiddersMax !== newMidMax) {\n //This is hella hacky, but for whatever reason if i do not use the 'setTimeout' call, i receive the error...\n //Warning: Cannot update a component (`Formik`) while rendering a different component (`Unknown`). To locate the bad setState() call inside `Unknown`, follow the stack trace as described in https://fb.me/setstate-in-render\n //For now, with the advice of another sr dev, using the setTimeout will allow me to conitnue with the story. We can revisit this later. - MR\n setTimeout(() => form.setFieldValue('midBiddersMax', newMidMax));\n }\n }\n }\n };\n\n return (\n
    \n {props.preferences && (\n \n {({ errors, values, submitCount }): JSX.Element => (\n <>\n \n
    \n {\n <>\n {/* NOTE: 2021/12/14 - This code will be removed in the future but it's hidden for now */}\n {/*
    \n
    \n \n
    \n
    */}\n\n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n \n\n
    \n\n \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n\n
    \n \n\n
    \n\n \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n\n
    \n \n\n
    \n\n \n
    \n
    \n
    \n
    \n \n }\n\n {!props.isReadOnly ? (\n \n
    \n \n props.onDiscardClick(values)}\n />\n
    \n {submitCount > 0 && (\n \n )}\n
    \n ) : (\n <>\n )}\n
    \n \n )}\n \n )}\n
    \n );\n};\n\nexport default PreferencesEditForm;\n","import { CommandManagerService } from '../../../../../services/command/command-manager-service';\nimport { addCommandToBatchCommandObject } from '../../../../../utils/command-manager-service';\n\nconst preferencesReducer: DispatchManagerReducer<\n CommandManagerService,\n DispatchManagerDispatchActions_Preferences\n> = (\n dispatchData: CommandManagerService,\n action: DispatchManagerDispatchAction,\n): CommandManagerService => {\n switch (action.type) {\n case 'update-bidders-ranges':\n case 'update-measurement-system':\n return addCommandToBatchCommandObject(dispatchData, action.data as ICommand);\n\n default:\n return dispatchData;\n }\n};\n\nexport default preferencesReducer;\n","import { isEqual } from 'lodash';\nimport React, { useCallback, useContext, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory } from 'react-router';\nimport { PreferencesBatchCommand } from '../../../../classes/commands/preferences/batch-commands/preferences-batch-command';\nimport { UpdateBiddersRangesCommand } from '../../../../classes/commands/preferences/update-bidders-ranges-command';\nimport { UpdateMeasurementSystemCommand } from '../../../../classes/commands/preferences/update-measurement-system-command';\nimport GeneralConstants from '../../../../constants/general';\nimport ApplicationRoutes from '../../../../constants/routes';\nimport useCommandManagerDispatcher from '../../../../hooks/dispatch-manager-helper/useDispatcherWithCommandManagerService';\nimport { FrozenEntitiesApi, PreferencesApi } from '../../../../services';\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\nimport { CommandManagerService } from '../../../../services/command/command-manager-service';\nimport generateBatchCommandInitializerReducer from '../../../../services/command/reducers/command-manager-batch-command-initializer-reducer';\nimport commandManagerDispatchReducer from '../../../../services/command/reducers/command-manager-dispatch-reducer';\nimport { DispatchManagerContext } from '../../../../services/dispatch-manager/DispatchManager';\nimport { useLogger } from '../../../../services/logger/Logger';\nimport { addCommandToBatchCommandObject } from '../../../../utils/command-manager-service';\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\nimport useDegradedActionNotifications from '../../../shared-page-components/hooks/useDegradedActionNotifications';\nimport PreferencesEditForm from './components/PreferencesEditForm';\nimport './PreferencesPage.scss';\nimport preferencesReducer from './reducers/preferences-reducer';\n\n// The Group Id for the batching of preferences commands\nconst preferencesGroupId = 'Preferences-Group-Id';\n\nconst PreferencesPage: React.FC = () => {\n const { t } = useTranslation();\n const logger = useLogger();\n const history = useHistory();\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n const { showSuccessNotification, showInfoNotification, showErrorNotification } = useContext(\n NotificationPanelContext,\n );\n const [preferencesToEdit, setPreferencesToEdit] = useState();\n const { dispatchAction } = useContext(DispatchManagerContext);\n const {\n initializeCommandManagerServiceOnDispatcher,\n commandManagerService,\n } = useCommandManagerDispatcher({ key: preferencesGroupId });\n\n const [systemSettingEntityIsFrozen, setSystemSettingEntityIsFrozen] = useState(false);\n const userIsAdmin = AuthenticationService.currentUserInfo?.userIsAdmin() ?? false;\n\n useDegradedActionNotifications('PreferencesPage');\n\n // Initial load of data\n useEffect(() => {\n const loadPreferences = async (): Promise => {\n try {\n showPageLoadingOverlay();\n //get the preferences from the prefs api\n const pref = await PreferencesApi.getPreferences();\n setPreferencesToEdit(pref);\n\n // NOTE: This page is not wired up to SignalR so we only perform this frozen entity check once on load\n const entityIsFrozen = await FrozenEntitiesApi.checkIfEntityIsFrozen(\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION,\n );\n\n setSystemSettingEntityIsFrozen(entityIsFrozen);\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('preferences:getPreferencesError'));\n history.push(ApplicationRoutes.ERROR_ERROR);\n } finally {\n hidePageLoadingOverlay();\n }\n };\n\n loadPreferences();\n }, [hidePageLoadingOverlay, showErrorNotification, showPageLoadingOverlay, t, history, logger]);\n\n // Register preference group id and the necessary reducers with the Command Manager Service\n useEffect(() => {\n const batchCommandInitializerReducer = generateBatchCommandInitializerReducer(\n PreferencesBatchCommand,\n );\n initializeCommandManagerServiceOnDispatcher(\n preferencesGroupId,\n batchCommandInitializerReducer,\n commandManagerDispatchReducer,\n preferencesReducer,\n );\n }, [initializeCommandManagerServiceOnDispatcher]);\n\n // Executes the preferences batch command of the given command manager\n const executeBatchCommand = useCallback(\n async (commandManagerObj?: CommandManagerService | undefined): Promise => {\n let success = false;\n if (!commandManagerObj) {\n return success;\n }\n\n // lets create a deep copy of the command manager service\n const newCommandManagerService = commandManagerObj.clone();\n\n const result = await newCommandManagerService.executeNextCommand();\n // If no command was present, null will be returned\n if (result === null) {\n return success;\n }\n\n success = true;\n // Update the dispatch data since we just mutated the commands in the command manager\n dispatchAction(preferencesGroupId, {\n data: newCommandManagerService,\n type: 'update-command-manager',\n });\n\n return success;\n },\n [dispatchAction],\n );\n\n const onSubmit = useCallback(\n async (preferences: Preferences) => {\n showPageLoadingOverlay();\n\n try {\n // lets see if anything actually changed\n if (isEqual(preferences, preferencesToEdit)) {\n showInfoNotification(t('general:noChanges'), t('general:noChangesWereMade'));\n return;\n }\n\n //lets store off the command manager that we will send off to execute its batch command\n let commandManagerObj = commandManagerService;\n\n //lets make sure we have a command manager service. if we dont, we messed up somewhere\n if (!commandManagerObj) {\n // if we got to this point, we are in a bad state, so lets throw an error so we know what happened\n throw new Error('Missing Command Manager Service');\n }\n\n //something about the preferences has changed, lets figure out what exactly\n if (!isEqual(preferences.measurementSystem, preferencesToEdit?.measurementSystem)) {\n // create the command to handle updating the measurement system\n // Lets add this to the commands. There shouldn't be any other commands batched up, but to continue with the same paradigm, lets add this command.\n // Lets pass through the batch command class so it can be generated if one doesn't exist.\n commandManagerObj = addCommandToBatchCommandObject(\n commandManagerObj,\n new UpdateMeasurementSystemCommand(preferences.measurementSystem.id),\n PreferencesBatchCommand,\n );\n }\n\n if (\n preferences.lowBiddersMax !== preferencesToEdit?.lowBiddersMax ||\n preferences.midBiddersMax !== preferencesToEdit?.midBiddersMax\n ) {\n // create the command to handle updating the bidders ranges for the color coding\n // Lets pass through the batch command class so it can be generated if one doesn't exist.\n commandManagerObj = addCommandToBatchCommandObject(\n commandManagerObj,\n new UpdateBiddersRangesCommand(preferences.lowBiddersMax, preferences.midBiddersMax),\n PreferencesBatchCommand,\n );\n }\n\n //TODO return a more appropriate response from the executeBatchCommands call once we have decided the object to send over from the command web api\n const result = await executeBatchCommand(commandManagerObj);\n\n if (result) {\n // lets update the preferences to edit now with the new preferences\n setPreferencesToEdit(preferences);\n showSuccessNotification(t('general:success'), t('preferences:updatePreferencesSuccess'));\n } else {\n showErrorNotification(t('general:error'), t('preferences:updatePreferencesError'));\n }\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('preferences:updatePreferencesError'));\n history.push(ApplicationRoutes.ERROR_ERROR);\n } finally {\n hidePageLoadingOverlay();\n }\n },\n [\n executeBatchCommand,\n commandManagerService,\n hidePageLoadingOverlay,\n showErrorNotification,\n showInfoNotification,\n showPageLoadingOverlay,\n showSuccessNotification,\n t,\n preferencesToEdit,\n history,\n logger,\n ],\n );\n\n const onDiscard = useCallback(\n (preferences: Preferences) => {\n if (!isEqual(preferences, preferencesToEdit)) {\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: async (): Promise => {\n try {\n //get the preferences from the prefs api so that we have the latest preferences since someone else could have modified it\n const pref = await PreferencesApi.getPreferences();\n\n //in order to allow the form to update, since the preferences in preferencesToEdit actually hasn't changed, we need to clear them out and set them again\n setPreferencesToEdit(undefined);\n setPreferencesToEdit(pref);\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('preferences:getPreferencesError'));\n history.push(ApplicationRoutes.ERROR_ERROR);\n } finally {\n hideConfirmationOverlay();\n }\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n }\n },\n [\n hideConfirmationOverlay,\n showConfirmationOverlay,\n showErrorNotification,\n t,\n preferencesToEdit,\n history,\n logger,\n ],\n );\n\n return (\n
    \n {systemSettingEntityIsFrozen ? (\n
    \n
    \n \n
    \n
    \n ) : (\n <>\n )}\n\n
    \n \n
    \n\n
    \n {preferencesToEdit && (\n \n )}\n
    \n
    \n );\n};\n\nexport default PreferencesPage;\n","import { Form, Formik } from 'formik';\nimport { isEqual } from 'lodash';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport * as Yup from 'yup';\nimport { UnitOfMeasure } from '../../../../../classes/odata/unit-of-measure';\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\nimport { getFormErrorMessages } from '../../../../../utils/forms';\nimport { nameof } from '../../../../../utils/nameof';\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\nimport FormErrorContainer from '../../../../common-page-components/forms/form-error-container/FormErrorContainer';\nimport FormFooter from '../../../../common-page-components/forms/FormFooter';\nimport FormTextInput from '../../../../common-page-components/forms/FormTextInput';\n\ninterface Props {\n unitOfMeasure: UnitOfMeasure;\n unitsOfMeasure: UnitOfMeasure[];\n isReadOnly: boolean;\n onAddClick: (unitOfMeasure: UnitOfMeasure) => void;\n onDiscardClick: (unitOfMeasure: UnitOfMeasure, resetForm: () => void) => void;\n}\n\nconst UnitOfMeasureForm: React.FC = (props) => {\n const { t } = useTranslation();\n\n const FormSchema = Yup.object().shape({\n oDataResourceName: Yup.string(),\n name: Yup.string()\n .trim()\n .max(\n EntityValidationConstants.UnitOfMeasureEntityLimits.Name_MaxLength,\n t('units-of-measure:maxLength', {\n maxLength: EntityValidationConstants.UnitOfMeasureEntityLimits.Name_MaxLength,\n }),\n )\n .required(t('units-of-measure:unitOfMeasureRequired')),\n });\n\n const uniqueUnitValidator = (value: string): string | void => {\n if (props.unitOfMeasure.name === value) {\n return;\n }\n\n value = value.trim().toLocaleLowerCase();\n\n if (props.unitsOfMeasure.find((unit) => unit?.name?.trim().toLocaleLowerCase() === value)) {\n return t('units-of-measure:mustBeUnique') as string;\n }\n };\n\n return (\n
    \n
    \n

    {t('general:create')}

    \n\n {\n props.onAddClick(values);\n actions.resetForm();\n }}\n validationSchema={FormSchema}\n >\n {({ errors, values, submitCount, resetForm }): JSX.Element => (\n
    \n
    \n
    \n ('name')}\n validator={uniqueUnitValidator}\n maxLength={EntityValidationConstants.UnitOfMeasureEntityLimits.Name_MaxLength}\n disabled={props.isReadOnly}\n />\n
    \n
    \n
    \n \n props.onDiscardClick(values, resetForm)}\n disabled={isEqual(values, props.unitOfMeasure) || props.isReadOnly}\n />\n
    \n
    \n
    \n \n {submitCount > 0 && (\n \n )}\n \n
    \n )}\n \n
    \n
    \n );\n};\n\nexport default UnitOfMeasureForm;\n","import React, { useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { UnitOfMeasure } from '../../../../../classes/odata/unit-of-measure';\nimport BTCard from '../../../../common-page-components/card/BTCard';\nimport { BTCardListing } from '../../../../common-page-components/cards-container/BTCardsContainer';\n\ninterface Props {\n unitOfMeasure: UnitOfMeasure;\n isReadOnly: boolean;\n onDeleteClick: (unitOfMeasure: UnitOfMeasure) => void;\n}\n\ninterface ReturnValue {\n generateBTCardListing: (\n unitOfMeasure: UnitOfMeasure,\n isReadOnly: boolean,\n onDeleteClick: (unitOfMeasure: UnitOfMeasure) => void,\n ) => BTCardListing;\n}\n\nconst useUnitOfMeasureCard = (): ReturnValue => {\n const generateBTCardListing = useCallback(\n (\n unitOfMeasure: UnitOfMeasure,\n isReadOnly: boolean,\n onDeleteClick: (unitOfMeasure: UnitOfMeasure) => void,\n ): BTCardListing => {\n return {\n searchData: [unitOfMeasure.name || ''],\n sortValue: unitOfMeasure.name?.toLowerCase() || '',\n cardJSX: (\n \n ),\n };\n },\n [],\n );\n\n return { generateBTCardListing };\n};\n\nconst UnitOfMeasureListing: React.FC = (props) => {\n const { unitOfMeasure, isReadOnly } = props;\n\n const { t } = useTranslation();\n\n return (\n props.onDeleteClick(unitOfMeasure),\n tooltip: t('general:delete'),\n disabled: isReadOnly,\n 'data-testid': 'unit-of-measure-delete',\n },\n ]}\n />\n );\n};\n\nexport { useUnitOfMeasureCard };\n\nexport default UnitOfMeasureListing;\n","import { isEqual } from 'lodash';\nimport React, { useCallback, useContext, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory } from 'react-router';\nimport { UnitOfMeasure } from '../../../../classes/odata/unit-of-measure';\nimport ApplicationRoutes from '../../../../constants/routes';\nimport { UnitOfMeasureApi } from '../../../../services';\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\nimport { useLogger } from '../../../../services/logger/Logger';\nimport BTCardsContainer from '../../../common-page-components/cards-container/BTCardsContainer';\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\nimport UnitOfMeasureForm from './components/UnitOfMeasureForm';\nimport { useUnitOfMeasureCard } from './components/UnitOfMeasureListing';\nimport './UnitOfMeasurePage.scss';\n\nconst getNewUnitOfMeasure = (): UnitOfMeasure => new UnitOfMeasure({ name: '' });\n\nconst UnitsOfMeasurePage: React.FC = () => {\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n const { showSuccessNotification, showErrorNotification } = useContext(NotificationPanelContext);\n\n const { t } = useTranslation();\n const logger = useLogger();\n const history = useHistory();\n const userIsAdmin = AuthenticationService.currentUserInfo?.userIsAdmin() ?? false;\n\n const [unitOfMeasureToEdit, setUnitOfMeasureToEdit] = useState(\n getNewUnitOfMeasure(),\n );\n const [unitsOfMeasure, setUnitsOfMeasure] = useState([]);\n\n const { generateBTCardListing } = useUnitOfMeasureCard();\n\n // Initial data load\n useEffect(() => {\n const loadUnitsOfMeasure = async (): Promise => {\n try {\n showPageLoadingOverlay();\n\n // NOTE: We do NOT have to check for frozen entities here, since units of measure exist only in the query database\n\n const units = await UnitOfMeasureApi.getAllUnitsOfMeasure();\n setUnitsOfMeasure(units);\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('general:pageLoadError'));\n history.push(ApplicationRoutes.ERROR_ERROR);\n } finally {\n hidePageLoadingOverlay();\n }\n };\n\n loadUnitsOfMeasure();\n }, [showPageLoadingOverlay, showErrorNotification, hidePageLoadingOverlay, t, history, logger]);\n\n const onAddClick = useCallback(\n async (unitOfMeasure: UnitOfMeasure): Promise => {\n try {\n showPageLoadingOverlay();\n\n const newUnit = await UnitOfMeasureApi.addUnitOfMeasure(\n new UnitOfMeasure({ ...unitOfMeasure, name: unitOfMeasure.name?.trim() }),\n );\n if (!newUnit) {\n throw Error(`Failed to add unit of measure '${unitOfMeasure.name}'`);\n }\n\n const newUnits = [...unitsOfMeasure, newUnit];\n\n setUnitsOfMeasure(newUnits);\n setUnitOfMeasureToEdit(getNewUnitOfMeasure());\n\n showSuccessNotification(t('general:success'), t('units-of-measure:successAdd'));\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('units-of-measure:errorAdd'));\n } finally {\n hidePageLoadingOverlay();\n }\n },\n [\n unitsOfMeasure,\n hidePageLoadingOverlay,\n showErrorNotification,\n showPageLoadingOverlay,\n showSuccessNotification,\n t,\n logger,\n ],\n );\n\n const onDiscardClick = useCallback(\n (unitOfMeasure: UnitOfMeasure, resetForm: () => void): void => {\n if (isEqual(unitOfMeasure, unitOfMeasureToEdit)) {\n resetForm();\n return;\n }\n\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: (): void => {\n resetForm();\n hideConfirmationOverlay();\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n },\n [hideConfirmationOverlay, showConfirmationOverlay, t, unitOfMeasureToEdit],\n );\n\n const onDeleteClick = (unitOfMeasure: UnitOfMeasure): void => {\n showConfirmationOverlay({\n text: t('units-of-measure:confirmDelete', { unitOfMeasure: unitOfMeasure.name }),\n buttons: [\n {\n text: t('general:yes'),\n onClick: async (): Promise => {\n hideConfirmationOverlay();\n showPageLoadingOverlay();\n\n try {\n await UnitOfMeasureApi.deleteUnitOfMeasure(unitOfMeasure);\n\n const updatedUnits = unitsOfMeasure.filter(\n (unit) => unit.name !== unitOfMeasure.name,\n );\n setUnitsOfMeasure(updatedUnits);\n\n showSuccessNotification(t('general:success'), t('units-of-measure:successDelete'));\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('units-of-measure:errorDelete'));\n } finally {\n hidePageLoadingOverlay();\n }\n },\n color: 'normal',\n },\n {\n text: t('general:no'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n };\n\n return (\n
    \n
    \n \n
    \n\n {/* If we're rendering in read-only mode, lets hide the form at the top that's always\n available for consistency with the other pages where the forms are only visible in edit mode */}\n
    \n \n
    \n\n
    \n \n generateBTCardListing(unitOfMeasure, !userIsAdmin, onDeleteClick),\n )}\n />\n
    \n
    \n );\n};\n\nexport default UnitsOfMeasurePage;\n","import React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\r\n\r\ninterface Props {\r\n location: string;\r\n locations: string[];\r\n setLocation: (location: string) => void;\r\n}\r\n\r\nconst LocationListing: React.FC = ({ location, locations, setLocation }) => {\r\n const { t } = useTranslation();\r\n\r\n return (\r\n
    \r\n

    {t('user-permissions:locations')}

    \r\n
    \r\n {locations.map((currLocation) => (\r\n \r\n {\r\n setLocation(currLocation);\r\n }}\r\n roundedCorners={true}\r\n />\r\n
    \r\n ))}\r\n
    \r\n
    \r\n );\r\n};\r\n\r\nexport default LocationListing;\r\n","import { ComboBox, ComboBoxChangeEvent } from '@progress/kendo-react-dropdowns';\r\nimport { Field, FieldProps } from 'formik';\r\nimport { get } from 'lodash';\r\nimport React from 'react';\r\nimport './Forms.scss';\r\n\r\ninterface Props {\r\n placeholderText: string;\r\n label: string;\r\n name: string;\r\n data: string[];\r\n validator?: (value: string) => string | void;\r\n}\r\n\r\nconst WrappedComboBox: React.FC = ({\r\n field,\r\n form,\r\n placeholderText,\r\n label,\r\n data,\r\n ...rest\r\n}) => {\r\n const errors = get(form.errors, field.name);\r\n const hasErrors = !!errors;\r\n\r\n const classNames = ['formInput'];\r\n if (hasErrors && form.submitCount) {\r\n classNames.push('formInputError');\r\n }\r\n\r\n // NOTE: Keep the field / rest props at the top so we can override the onChange property\r\n return (\r\n <>\r\n \r\n {\r\n form.setFieldValue(field.name, e.value);\r\n }}\r\n />\r\n \r\n );\r\n};\r\n\r\nconst FormComboBox: React.FC = (props) => {\r\n return (\r\n
    \r\n \r\n
    \r\n );\r\n};\r\n\r\nexport default FormComboBox;\r\n","import { MultiSelect } from '@progress/kendo-react-dropdowns';\r\nimport { Field, FieldInputProps, FieldProps } from 'formik';\r\nimport { get, sortBy } from 'lodash';\r\nimport React from 'react';\r\nimport './Forms.scss';\r\n\r\nexport interface FormMultiSelectOption {\r\n id: string;\r\n name: string;\r\n}\r\n\r\ninterface FieldValue {\r\n id: string;\r\n // NOTE: using any here to make a dict type\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n [key: string]: any;\r\n}\r\n\r\ninterface Props {\r\n placeholderText: string;\r\n label: string;\r\n name: string;\r\n data: FormMultiSelectOption[];\r\n validator?: (value: FormMultiSelectOption[]) => string | void;\r\n}\r\n\r\nconst getValueForMultiSelect = (\r\n data: FormMultiSelectOption[],\r\n field: FieldInputProps,\r\n): FieldValue[] => {\r\n return !field.value\r\n ? []\r\n : sortBy(\r\n data.filter((v) => field.value.find((fv) => fv.id === v.id) !== undefined),\r\n (v) => v.name,\r\n );\r\n};\r\n\r\nconst WrappedMultiSelect: React.FC = ({\r\n field,\r\n form,\r\n placeholderText,\r\n label,\r\n data,\r\n ...rest\r\n}) => {\r\n const errors = get(form.errors, field.name);\r\n const hasErrors = !!errors;\r\n\r\n const classNames = ['formInput'];\r\n if (hasErrors && form.submitCount) {\r\n classNames.push('formInputError');\r\n }\r\n\r\n // NOTE: Keep the field / rest props at the top so we can override the onChange property\r\n return (\r\n <>\r\n \r\n v.name) : []}\r\n {...field}\r\n {...rest}\r\n value={getValueForMultiSelect(data, field)}\r\n onChange={(newValue): void => {\r\n // Sort the values before we set them, to try to prevent data getting out of order and changing unnecessarily\r\n const newValues = sortBy(newValue.target.value as FormMultiSelectOption[], (v) => v.name);\r\n form.setFieldValue(field.name, newValues);\r\n }}\r\n />\r\n \r\n );\r\n};\r\n\r\nconst FormMultiSelect: React.FC = (props) => {\r\n return (\r\n
    \r\n \r\n
    \r\n );\r\n};\r\n\r\nexport default FormMultiSelect;\r\n","import { Form, Formik } from 'formik';\r\nimport React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport * as Yup from 'yup';\r\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\r\nimport UserRoles from '../../../../../constants/users';\r\nimport { UserRolesValues } from '../../../../../constants/users/user-roles';\r\nimport { AuthenticationService } from '../../../../../services/authentication/authentication-service';\r\nimport { getFormErrorMessages } from '../../../../../utils/forms';\r\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\r\nimport FormErrorContainer from '../../../../common-page-components/forms/form-error-container/FormErrorContainer';\r\nimport FormComboBox from '../../../../common-page-components/forms/FormComboBox';\r\nimport FormFooter from '../../../../common-page-components/forms/FormFooter';\r\nimport FormMultiSelect from '../../../../common-page-components/forms/FormMultiSelect';\r\nimport { FormMultiSelectOption } from './../../../../common-page-components/forms/FormMultiSelect';\r\nimport FormTextInput from './../../../../common-page-components/forms/FormTextInput';\r\n\r\nconst UserRoleSchema = Yup.object().required().shape({\r\n id: Yup.string(),\r\n name: Yup.string(),\r\n});\r\n\r\ninterface Props {\r\n domains: string[];\r\n locations: string[];\r\n user: User;\r\n users: User[];\r\n onSubmitClick: (user: User) => void;\r\n onDiscardClick: (user: User) => void;\r\n}\r\n\r\nconst UserEditForm: React.FC = (props) => {\r\n const { t } = useTranslation();\r\n\r\n const FormSchema = Yup.object().shape({\r\n id: Yup.string(),\r\n email: Yup.string()\r\n .trim()\r\n .max(\r\n EntityValidationConstants.UserEntityLimits.Email_MaxLength,\r\n t('user-permissions:emailMaxLength', {\r\n maxLength: EntityValidationConstants.UserEntityLimits.Email_MaxLength,\r\n }),\r\n )\r\n .email('The email address is not valid')\r\n .required('Email address is a required field'),\r\n location: Yup.string()\r\n .trim()\r\n .max(\r\n EntityValidationConstants.UserEntityLimits.Location_MaxLength,\r\n t('user-permissions:locationMaxLength', {\r\n maxLength: EntityValidationConstants.UserEntityLimits.Location_MaxLength,\r\n }),\r\n )\r\n .required('Location is a required field'),\r\n roles: Yup.array().min(1, 'At least one role must be specified').of(UserRoleSchema).required(),\r\n isNew: Yup.boolean(),\r\n });\r\n\r\n const userInformation = AuthenticationService.currentUserInfo;\r\n\r\n const isUserCurrentUser = (): boolean => {\r\n return userInformation !== null && userInformation.email === props.user.email;\r\n };\r\n\r\n const getAvailableUserRoles = (): FormMultiSelectOption[] => {\r\n let roles: UserRole[] = [];\r\n\r\n if (userInformation) {\r\n if (userInformation.userIsAdmin()) {\r\n roles = [UserRoles.Admin, UserRoles.ProjectAdmin, UserRoles.Contributor];\r\n } else {\r\n roles = [UserRoles.ProjectAdmin, UserRoles.Contributor];\r\n }\r\n }\r\n\r\n return roles;\r\n };\r\n\r\n const uniqueEmailValidator = (emailAddress: string): string | void => {\r\n if (props.user.email === emailAddress) {\r\n return;\r\n }\r\n emailAddress = emailAddress.trim().toLowerCase();\r\n const clientDomains = props.domains.map((domain) => domain.trim().toLowerCase());\r\n const emailAddressDomain = emailAddress.split('@').pop();\r\n\r\n // NOTE: When we are editing a user, the email address is not editable so we don't have to worry about\r\n // checking to make sure the user with the same email address isn't the user being edited or if the\r\n // user object is new\r\n if (props.users.find((v) => v.email.trim().toLowerCase() === emailAddress)) {\r\n return t('user-permissions:emailMustBeUnique').toString();\r\n }\r\n\r\n if (!clientDomains.some((domain) => domain === emailAddressDomain)) {\r\n return t('user-permissions:emailDomainMustMatch', {\r\n clientDomains: clientDomains.join(', '),\r\n }).toString();\r\n }\r\n };\r\n\r\n const rolesValidator = (newRoles: FormMultiSelectOption[]): string | void => {\r\n if (isUserCurrentUser()) {\r\n if (userInformation?.userIsAdmin()) {\r\n // Don't allow an Admin user to remove Admin role from themselves\r\n if (!newRoles.some((r) => r.id === UserRoles[UserRolesValues.Admin].id)) {\r\n return t('user-permissions:cannotRemoveAdminRoleFromSelf').toString();\r\n }\r\n } else if (userInformation?.userIsProjectAdmin()) {\r\n // Don't allow a Project Admin user to remove Project Admin role from themselves\r\n if (!newRoles.some((r) => r.id === UserRoles[UserRolesValues.ProjectAdmin].id)) {\r\n return t('user-permissions:cannotRemoveProjectAdminRoleFromSelf').toString();\r\n }\r\n }\r\n }\r\n };\r\n\r\n // NOTE: With Formik, once we set the 'initialValues' property, updating it will not update the form values unless we set the 'enableReinitialize' flag\r\n // so we do not even render the Formik element unless the object we bind to its initial values is defined\r\n return (\r\n
    \r\n

    \r\n {`${props.user && props.user.isNew ? t('general:create') : t('general:edit')} ${t(\r\n 'user-permissions:user',\r\n )}`}\r\n

    \r\n\r\n {props.user && (\r\n \r\n {({ errors, values, submitCount }): JSX.Element => (\r\n
    \r\n {\r\n <>\r\n
    \r\n {!props.user.isNew ? (\r\n <>\r\n
    \r\n \r\n
    {props.user.email}
    \r\n
    \r\n \r\n ) : (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n )}\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n }\r\n\r\n \r\n
    \r\n \r\n {\r\n props.onDiscardClick(values);\r\n }}\r\n />\r\n
    \r\n {submitCount > 0 && (\r\n \r\n )}\r\n
    \r\n
    \r\n )}\r\n \r\n )}\r\n
    \r\n );\r\n};\r\n\r\nexport default UserEditForm;\r\n","import React, { useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { UserRolesValues } from '../../../../../constants/users/user-roles';\r\nimport { AuthenticationService } from '../../../../../services/authentication/authentication-service';\r\nimport { getEmailWithoutDomain } from '../../../../../utils/strings';\r\nimport BTCard from '../../../../common-page-components/card/BTCard';\r\nimport {\r\n BTCardListing,\r\n BTCardsContainerHighlightableText,\r\n} from '../../../../common-page-components/cards-container/BTCardsContainer';\r\nimport './UserListing.scss';\r\n\r\ninterface Props {\r\n user: User;\r\n isReadOnly: boolean;\r\n editUserButtonClick: (user: User) => void;\r\n deleteUserButtonClick: (user: User) => void;\r\n}\r\n\r\ninterface ReturnValue {\r\n generateBTCardListing: (\r\n user: User,\r\n isReadOnly: boolean,\r\n editUserButtonClick: (user: User) => void,\r\n deleteUserButtonClick: (user: User) => void,\r\n ) => BTCardListing;\r\n}\r\n\r\nconst useUserListing = (): ReturnValue => {\r\n const generateBTCardListing = useCallback(\r\n (\r\n user: User,\r\n isReadOnly: boolean,\r\n editUserButtonClick: (user: User) => void,\r\n deleteUserButtonClick: (user: User) => void,\r\n ): BTCardListing => {\r\n return {\r\n searchData: [user.email, user.location, (user.roles || []).map((v) => v.name).join(' ')],\r\n sortValue: user.email,\r\n cardJSX: (\r\n \r\n ),\r\n };\r\n },\r\n [],\r\n );\r\n\r\n return {\r\n generateBTCardListing,\r\n };\r\n};\r\n\r\nconst UserListing: React.FC = ({\r\n user,\r\n isReadOnly,\r\n editUserButtonClick,\r\n deleteUserButtonClick,\r\n}) => {\r\n const { t } = useTranslation();\r\n const currentUser = AuthenticationService.currentUserInfo;\r\n\r\n const isUserCurrentUser = (): boolean => {\r\n return currentUser !== null && currentUser.email === user.email;\r\n };\r\n\r\n const isUserHigherRole = (): boolean => {\r\n if (currentUser && user.roles.find((v) => v.id === UserRolesValues.Admin)) {\r\n if (!currentUser.userIsAdmin()) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n };\r\n\r\n const isUserAdminOrProjectAdmin = (): boolean => {\r\n if (currentUser && (currentUser.userIsAdmin() || currentUser.userIsProjectAdmin())) {\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n const getTooltipForEditButton = (): string => {\r\n if (!isUserAdminOrProjectAdmin()) {\r\n return '';\r\n } else if (isUserHigherRole()) {\r\n return t('user-permissions:cannotEditAdminUserAsProjectAdmin');\r\n } else if (isReadOnly) {\r\n return '';\r\n }\r\n return t('general:edit');\r\n };\r\n\r\n const getTooltipForDeleteButton = (): string => {\r\n if (!isUserAdminOrProjectAdmin()) {\r\n return '';\r\n } else if (isUserCurrentUser()) {\r\n return t('user-permissions:cannotDeleteOwnUser');\r\n } else if (isUserHigherRole()) {\r\n return t('user-permissions:cannotEditAdminUserAsProjectAdmin');\r\n } else if (isReadOnly) {\r\n return '';\r\n }\r\n return t('general:delete');\r\n };\r\n\r\n return (\r\n {\r\n editUserButtonClick(user);\r\n },\r\n tooltip: getTooltipForEditButton(),\r\n disabled: isUserHigherRole() || isReadOnly,\r\n 'data-testid': 'user-edit',\r\n },\r\n {\r\n buttonIcon: 'trash',\r\n onClick: (): void => {\r\n deleteUserButtonClick(user);\r\n },\r\n tooltip: getTooltipForDeleteButton(),\r\n disabled: isUserCurrentUser() || isUserHigherRole() || isReadOnly,\r\n 'data-testid': 'user-delete',\r\n },\r\n ]}\r\n >\r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n \r\n\r\n {!user.roles.length ? (\r\n
    ({t('user-permissions:noRoles')})
    \r\n ) : (\r\n
    \r\n {user.roles.map((currRole: UserRole) => {\r\n return (\r\n
    \r\n \r\n
    \r\n );\r\n })}\r\n
    \r\n )}\r\n
    \r\n
    \r\n
    \r\n \r\n );\r\n};\r\n\r\nexport { useUserListing };\r\n\r\nexport default UserListing;\r\n","import { isEqual, uniq } from 'lodash';\r\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router-dom';\r\nimport { Collapse } from 'reactstrap';\r\nimport GeneralConstants from '../../../../constants/general';\r\nimport ApplicationRoutes from '../../../../constants/routes';\r\nimport SystemValues from '../../../../constants/system-values';\r\nimport { FrozenEntitiesApi, SystemValuesApi, UserApi } from '../../../../services';\r\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\r\nimport { useLogger } from '../../../../services/logger/Logger';\r\nimport { scrollToRef } from '../../../../utils/general';\r\nimport BTCardsContainer from '../../../common-page-components/cards-container/BTCardsContainer';\r\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport BTFloatingIconButton from '../../../common-page-components/controls/floating-icon-button/BTFloatingIconButton';\r\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\r\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\r\nimport useDegradedActionNotifications from '../../../shared-page-components/hooks/useDegradedActionNotifications';\r\nimport LocationListing from './components/LocationListing';\r\nimport UserEditForm from './components/UserEditForm';\r\nimport { useUserListing } from './components/UserListing';\r\nimport './UserPermissionsPage.scss';\r\n\r\nconst UserPermissionsPage: React.FC = () => {\r\n const { t } = useTranslation();\r\n const logger = useLogger();\r\n const history = useHistory();\r\n\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n const { showSuccessNotification, showInfoNotification, showErrorNotification } = useContext(\r\n NotificationPanelContext,\r\n );\r\n const [isEditAreaOpen, setIsEditAreaOpen] = useState(false);\r\n const [userToEdit, setUserToEdit] = useState();\r\n const [users, setUsers] = useState([]);\r\n const [domains, setDomains] = useState([]);\r\n const [location, setLocation] = useState(t('general:all'));\r\n const [locations, setLocations] = useState([]);\r\n const [locationsToDisplay, setLocationsToDisplay] = useState([]);\r\n const [filteredUsers, setFilteredUsers] = useState([]);\r\n const userPermissionsPageEditAreaRef = useRef(null);\r\n\r\n const [systemSettingEntityIsFrozen, setSystemSettingEntityIsFrozen] = useState(false);\r\n const userIsAdminOrProjectAdmin =\r\n (AuthenticationService.currentUserInfo?.userIsAdmin() ||\r\n AuthenticationService.currentUserInfo?.userIsProjectAdmin()) ??\r\n false;\r\n\r\n const { generateBTCardListing } = useUserListing();\r\n\r\n const updateLocations = useCallback(\r\n (users: User[]): void => {\r\n const newLocations = uniq(users.map((user) => user.location)).sort();\r\n setLocations(newLocations);\r\n setLocationsToDisplay(\r\n newLocations.length > 1 ? [t('general:all'), ...newLocations] : newLocations,\r\n );\r\n\r\n if (newLocations.length === 1) {\r\n setLocation(newLocations[0]);\r\n }\r\n },\r\n [t],\r\n );\r\n\r\n useDegradedActionNotifications('UserPermissionsPage');\r\n\r\n // Initial load of data\r\n useEffect(() => {\r\n const loadUsers = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // NOTE: This page is not wired up to SignalR so we only perform this frozen entity check once on load\r\n const entityIsFrozen = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION,\r\n );\r\n\r\n setSystemSettingEntityIsFrozen(entityIsFrozen);\r\n\r\n const users = await UserApi.getAllUsers();\r\n setUsers(users);\r\n\r\n const domains = await SystemValuesApi.getSystemValue(SystemValues.DOMAINS);\r\n if (domains != null) {\r\n setDomains(domains.split(','));\r\n }\r\n\r\n updateLocations(users);\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('general:pageLoadError'));\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n loadUsers();\r\n }, [\r\n hidePageLoadingOverlay,\r\n history,\r\n showErrorNotification,\r\n showPageLoadingOverlay,\r\n t,\r\n updateLocations,\r\n logger,\r\n ]);\r\n\r\n useEffect(() => {\r\n setFilteredUsers(\r\n location === '' || location === t('general:all')\r\n ? users\r\n : users.filter((user) => {\r\n return user.location === location;\r\n }),\r\n );\r\n }, [location, users, setFilteredUsers, t]);\r\n\r\n const getNewUser = (): User => ({\r\n id: '',\r\n email: '',\r\n location: '',\r\n roles: [],\r\n isNew: true,\r\n });\r\n\r\n const toggleCollapse = (open: boolean): void => {\r\n setIsEditAreaOpen(open);\r\n\r\n if (open) {\r\n setTimeout(() => {\r\n scrollToRef(userPermissionsPageEditAreaRef);\r\n }, 500);\r\n }\r\n };\r\n\r\n const onSubmit = useCallback(\r\n async (user: User) => {\r\n showPageLoadingOverlay();\r\n\r\n const closeEditAreaAndClearOutEditModel = (): void => {\r\n setIsEditAreaOpen(false);\r\n\r\n // Delay this slightly so the edit area has time to animate closed\r\n setTimeout(() => {\r\n setUserToEdit(null);\r\n }, 250);\r\n };\r\n\r\n try {\r\n // If it's a new user, add them\r\n if (user.isNew) {\r\n try {\r\n user.email = user.email.toLowerCase();\r\n const newUser = await UserApi.addUser(user);\r\n newUser.isNew = false;\r\n const newUsers = [...users, newUser];\r\n setUsers(newUsers);\r\n updateLocations(newUsers);\r\n\r\n closeEditAreaAndClearOutEditModel();\r\n\r\n showSuccessNotification(t('general:success'), t('user-permissions:createUserSuccess'));\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('user-permissions:createUserError'));\r\n }\r\n }\r\n // If it's an existing user, update them\r\n else {\r\n try {\r\n if (isEqual(user, userToEdit)) {\r\n closeEditAreaAndClearOutEditModel();\r\n\r\n showInfoNotification(t('general:noChanges'), t('general:noChangesWereMade'));\r\n return;\r\n }\r\n await UserApi.editUser(user);\r\n const usersClone = [...users];\r\n\r\n const index = usersClone.findIndex((u) => u.email === user.email);\r\n\r\n if (index === -1) {\r\n throw new Error(`Could not find user with email '${user.email}'.`);\r\n }\r\n\r\n usersClone[index] = user;\r\n\r\n setUsers(usersClone);\r\n updateLocations(usersClone);\r\n\r\n closeEditAreaAndClearOutEditModel();\r\n\r\n showSuccessNotification(t('general:success'), t('user-permissions:updateUserSuccess'));\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('user-permissions:updateUserError'));\r\n }\r\n }\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n },\r\n [\r\n hidePageLoadingOverlay,\r\n showErrorNotification,\r\n showInfoNotification,\r\n showPageLoadingOverlay,\r\n showSuccessNotification,\r\n t,\r\n updateLocations,\r\n userToEdit,\r\n users,\r\n logger,\r\n ],\r\n );\r\n\r\n const onDiscard = useCallback(\r\n (user: User) => {\r\n const discardChanges = (): void => {\r\n setIsEditAreaOpen(false);\r\n\r\n // Delay this slightly so the edit area has time to animate closed\r\n setTimeout(() => {\r\n setUserToEdit(null);\r\n }, 250);\r\n };\r\n\r\n if (!isEqual(user, userToEdit)) {\r\n showConfirmationOverlay({\r\n text: t('general:discardConfirmation'),\r\n buttons: [\r\n {\r\n text: t('general:discard'),\r\n onClick: (): void => {\r\n discardChanges();\r\n hideConfirmationOverlay();\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:cancel'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n } else {\r\n discardChanges();\r\n }\r\n },\r\n [hideConfirmationOverlay, showConfirmationOverlay, t, userToEdit],\r\n );\r\n\r\n const onAddClick = useCallback(() => {\r\n setUserToEdit(getNewUser());\r\n toggleCollapse(true);\r\n }, []);\r\n\r\n const onEditClick = useCallback((user: User) => {\r\n setUserToEdit(user);\r\n toggleCollapse(true);\r\n }, []);\r\n\r\n const onDeleteClick = useCallback(\r\n (user: User) => {\r\n // NOTE: The delete button on the card listing should be disabled so if we get to this\r\n // point, we can assume things are OK and the server can confirm any errors\r\n showConfirmationOverlay({\r\n text: t('user-permissions:confirmDelete', { email: user.email }),\r\n buttons: [\r\n {\r\n text: t('general:yes'),\r\n onClick: async (): Promise => {\r\n hideConfirmationOverlay();\r\n showPageLoadingOverlay();\r\n\r\n try {\r\n await UserApi.deleteUser(user);\r\n const updatedUsers = users.filter((u) => u.email !== user.email);\r\n setUsers(updatedUsers);\r\n updateLocations(updatedUsers);\r\n\r\n showSuccessNotification(\r\n t('general:success'),\r\n t('user-permissions:deleteUserSuccess'),\r\n );\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('user-permissions:deleteUserError'));\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:no'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n },\r\n [\r\n showConfirmationOverlay,\r\n t,\r\n hideConfirmationOverlay,\r\n showPageLoadingOverlay,\r\n users,\r\n updateLocations,\r\n showSuccessNotification,\r\n showErrorNotification,\r\n hidePageLoadingOverlay,\r\n logger,\r\n ],\r\n );\r\n\r\n return (\r\n <>\r\n
    \r\n {systemSettingEntityIsFrozen ? (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n \r\n
    \r\n\r\n
    \r\n {\r\n setLocation(location);\r\n }}\r\n />\r\n
    \r\n\r\n
    \r\n \r\n
    \r\n
    \r\n {userToEdit && domains ? (\r\n \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n \r\n generateBTCardListing(\r\n v,\r\n isEditAreaOpen || systemSettingEntityIsFrozen || !userIsAdminOrProjectAdmin,\r\n onEditClick,\r\n onDeleteClick,\r\n ),\r\n )}\r\n />\r\n
    \r\n\r\n \r\n
    \r\n \r\n );\r\n};\r\n\r\nexport default UserPermissionsPage;\r\n","import { CommandBase } from '../CommandBase';\n\nexport class ClearSelectedBidderOnBidPackage extends CommandBase {\n public bidPackageId: string;\n\n constructor(bidPackageId: string) {\n super(\n 'DESTINI.BidDay.Commands.BidPackages.ClearSelectedBidderOnBidPackage',\n 'bid-package/clear-selected-bidder',\n 'post',\n );\n\n this.bidPackageId = bidPackageId;\n }\n}\n","import { CommandBase } from '../CommandBase';\n\nexport class DeleteBidPackageBidderCommand extends CommandBase {\n constructor(public bidPackageId: string, public companyName: string) {\n super(\n 'DESTINI.BidDay.Commands.BidPackages.DeleteBidPackageBidder',\n 'bid-package/delete-bidder',\n 'post',\n );\n }\n}\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class DeleteBidPackageLineItemCommand extends CommandBase {\r\n public bidPackageId: string;\r\n public lineItemId: string;\r\n\r\n constructor(bidPackageId: string, lineItemId: string) {\r\n super('DESTINI.BidDay.Commands.BidPackages.DeleteBidPackageLineItem', '', 'none');\r\n this.bidPackageId = bidPackageId;\r\n this.lineItemId = lineItemId;\r\n }\r\n}\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class DeleteBidderRequirementFulfillmentOnBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public description: string,\r\n public isTradeRequirement: boolean,\r\n public companyName: string,\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.DeleteBidderRequirementFulfillmentOnBidPackage',\r\n 'bid-package/delete-bidder-requirement-fulfillment',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class DeleteLineItemBidOnBidPackageCommand extends CommandBase {\r\n constructor(public bidPackageId: string, public lineItemId: string, public companyName: string) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.DeleteLineItemBidOnBidPackage',\r\n 'bid-package/delete-line-item-bid',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { CommandBase } from '../CommandBase';\n\nexport class SetBidderOrderCommand extends CommandBase {\n constructor(public bidPackageId: string, public bidderCompanyName: string, public order: number) {\n super(\n 'DESTINI.BidDay.Commands.BidPackages.SetBidderOrder',\n 'bid-package/set-bidder-order',\n 'post',\n );\n }\n}\n","import { CommandBase } from '../CommandBase';\nimport { BidderStatus } from '../../odata/bidder';\n\nexport class SetBidderStatusCommand extends CommandBase {\n constructor(\n public bidPackageId: string,\n public bidderCompanyName: string,\n public status: BidderStatus,\n ) {\n super(\n 'DESTINI.BidDay.Commands.BidPackages.SetBidderStatus',\n 'bid-package/set-bidder-status',\n 'post',\n );\n }\n}\n","import { CommandBase } from '../CommandBase';\n\nexport class SetSelectedBidderOnBidPackage extends CommandBase {\n public bidPackageId: string;\n public selectedBidderCompanyName: string;\n\n constructor(bidPackageId: string, selectedBidderCompanyName: string) {\n super(\n 'DESTINI.BidDay.Commands.BidPackages.SetSelectedBidderOnBidPackage',\n 'bid-package/set-selected-bidder',\n 'post',\n );\n\n this.bidPackageId = bidPackageId;\n this.selectedBidderCompanyName = selectedBidderCompanyName;\n }\n}\n","import { CommandBase } from '../CommandBase';\n\nexport class UpdateBidPackageLineItemOrderCommand extends CommandBase {\n public bidPackageId: string;\n public lineItemId: string | null;\n public alternateName: string | null;\n public order: number;\n\n constructor(\n bidPackageId: string,\n lineItemId: string | null,\n alternameName: string | null,\n order: number,\n ) {\n super(\n 'DESTINI.BidDay.Commands.BidPackages.UpdateBidPackageLineItemOrder',\n '/bid-package/update-line-item-order',\n 'post',\n );\n this.bidPackageId = bidPackageId;\n this.lineItemId = lineItemId;\n this.alternateName = alternameName;\n this.order = order;\n }\n}\n","import { CommandBase } from '../CommandBase';\n\nexport class UpdateBidPackageLineItemGroupOrderCommand extends CommandBase {\n public bidPackageId: string;\n public classifications: string[] | null;\n public alternateName: string | null;\n public order: number;\n\n constructor(\n bidPackageId: string,\n classifications: string[] | null,\n alternameName: string | null,\n order: number,\n ) {\n super(\n 'DESTINI.BidDay.Commands.BidPackages.UpdateBidPackageLineItemGroupOrder',\n '/bid-package/update-line-item-group-order',\n 'post',\n );\n this.bidPackageId = bidPackageId;\n this.classifications = classifications;\n this.alternateName = alternameName;\n this.order = order;\n }\n}\n","const BID_PACKAGE_AUTOSAVE_TIMEOUT = 30_000;\r\n\r\n// A constant for what we consider \"a lot\" of line items on a bid package.\r\n// NOTE: This is subject to change in the future, as we get a better feel for user data load.\r\nconst BID_PACKAGE_LINEITEMS_PERFORMANCE_THRESHOLD = 200;\r\n\r\n// A constant for what may take a while to process on the server for adding line items\r\nconst BID_PACKAGE_LINEITEMS_ADD_THRESHOLD = 100;\r\n\r\nconst BidPackageConstants = {\r\n Config: { BID_PACKAGE_AUTOSAVE_TIMEOUT },\r\n\r\n BID_PACKAGE_LINEITEMS_ADD_THRESHOLD,\r\n BID_PACKAGE_LINEITEMS_PERFORMANCE_THRESHOLD,\r\n\r\n GridSectionIds: {\r\n ADJUSTMENTS: 'ADJUSTMENTS',\r\n ADJUSTMENTS_BID_PACKAGE_TOTALS: 'ADJUSTMENTS_BID_PACKAGE_TOTALS',\r\n BID_PACKAGE_HEADER: 'BID_PACKAGE_HEADER',\r\n BID_PACKAGE_TOTALS: 'BID_PACKAGE_TOTALS',\r\n REQUIREMENTS: 'REQUIREMENTS',\r\n LINE_ITEMS: 'LINE_ITEMS',\r\n LINE_ITEMS_HEADER: 'LINE_ITEMS_HEADER',\r\n },\r\n};\r\n\r\nexport default BidPackageConstants;\r\n","import React, { useEffect, useRef, useState } from 'react';\r\nimport { Observable } from 'rxjs';\r\nimport {\r\n useObservableWithBehaviorSubject,\r\n useObservableWithValue,\r\n} from '../../../../hooks/observables/useObservable';\r\n\r\ninterface CellRefMapping {\r\n gridSectionId: string;\r\n rowNumber: number;\r\n element: HTMLElement;\r\n}\r\n\r\n// A status object that we can use to tell the grid when and how to update\r\nexport interface BTGridRerenderStatus {\r\n rerenderId: string;\r\n rowsChanged: boolean;\r\n primaryGridColumnsChanged: boolean;\r\n}\r\n\r\ninterface BTGridContainerContextInterface {\r\n // State variables and setter functions\r\n\r\n // A nullable ID that we can set or null out to tell the grid rows to force them to render, even if nothing else changed\r\n rerenderStatus: BTGridRerenderStatus | null;\r\n setRerenderStatus: React.Dispatch>;\r\n\r\n // Ref variables\r\n elementBeingDragged: React.MutableRefObject;\r\n lastMouseCoordinates: React.MutableRefObject<{ x: number; y: number } | null>;\r\n rowHeightCollections: React.MutableRefObject;\r\n itemBeingDraggedInfo: React.MutableRefObject;\r\n\r\n // Observables and setter functions\r\n collapsedRowsChange$: Observable;\r\n rowCheckboxClick$: Observable;\r\n rowClick$: Observable;\r\n rowMouseEnter$: Observable;\r\n rowMouseLeave$: Observable;\r\n selectedRowsChange$: Observable;\r\n itemsReordered$: Observable;\r\n setCellRef$: Observable;\r\n dragStatusChanged$: Observable;\r\n\r\n onCollapsedRowsChange: (newVal: GridSectionCollapsedRowsMapping[]) => void;\r\n onRowCheckboxClick: (newVal: GridSectionRowMetadataMapping) => void;\r\n onRowClick: (newVal: GridSectionRowMetadataMapping) => void;\r\n onRowMouseEnter: (newVal: GridSectionRowNumberMapping) => void;\r\n onRowMouseLeave: (newVal: GridSectionRowNumberMapping) => void;\r\n onSelectedRowsChange: (newVal: GridSectionRowMetadataMapping[]) => void;\r\n onItemsReordered: (newVal: BTGridItemsReorderedInfo) => void;\r\n onSetCellRef: (newVal: CellRefMapping) => void;\r\n onDragStatusChanged: (newVal: boolean) => void;\r\n}\r\n\r\nconst BTGridContainerContext = React.createContext(\r\n {} as BTGridContainerContextInterface,\r\n);\r\n\r\nconst BTGridContainerContextProvider: React.FC = ({ children }) => {\r\n // Observables\r\n const [rowMouseEnter$, onRowMouseEnter] = useObservableWithValue();\r\n\r\n const [rowMouseLeave$, onRowMouseLeave] = useObservableWithValue();\r\n\r\n const [itemsReordered$, onItemsReordered] = useObservableWithValue();\r\n\r\n const [rowCheckboxClick$, onRowCheckboxClick] = useObservableWithValue<\r\n GridSectionRowMetadataMapping\r\n >();\r\n\r\n const [rowClick$, onRowClick] = useObservableWithValue();\r\n\r\n const [setCellRef$, onSetCellRef] = useObservableWithValue();\r\n\r\n const [dragStatusChanged$, onDragStatusChanged] = useObservableWithValue();\r\n\r\n // NOTE: The selected rows observable is underpinned by a behavior subject, which will broadcast\r\n // its value immediately upon subscription by calling code\r\n const [selectedRowsChange$, onSelectedRowsChange] = useObservableWithBehaviorSubject<\r\n GridSectionRowMetadataMapping[]\r\n >([]);\r\n\r\n // NOTE: The collapsed rows observable is underpinned by a behavior subject, which will broadcast\r\n // its value immediately upon subscription by calling code\r\n const [collapsedRowsChange$, onCollapsedRowsChange] = useObservableWithBehaviorSubject<\r\n GridSectionCollapsedRowsMapping[]\r\n >([]);\r\n\r\n // State variables\r\n const [rerenderStatus, setRerenderStatus] = useState(null);\r\n\r\n // Ref variables\r\n const elementBeingDragged = useRef(null);\r\n const lastMouseCoordinates = useRef<{ x: number; y: number } | null>(null);\r\n const rowHeightCollections = useRef([]);\r\n const itemBeingDraggedInfo = useRef(null);\r\n\r\n useEffect(() => {\r\n let mouseMoveEventTimer: NodeJS.Timeout | null;\r\n\r\n const mouseMoveEventHandler = (e: MouseEvent): void => {\r\n if (mouseMoveEventTimer) {\r\n return;\r\n }\r\n\r\n if (itemBeingDraggedInfo.current) {\r\n // Only update things every so often since mouse events come in fast and furious\r\n mouseMoveEventTimer = setTimeout(() => {\r\n lastMouseCoordinates.current = {\r\n x: e.x + window.pageXOffset,\r\n y: e.y + window.pageYOffset,\r\n };\r\n\r\n mouseMoveEventTimer = null;\r\n }, 25);\r\n } else {\r\n if (lastMouseCoordinates.current) {\r\n lastMouseCoordinates.current = null;\r\n }\r\n }\r\n };\r\n\r\n // We watch for the pointer up event on the window, in case the user released the pointer but wasn't over\r\n // any of parts of the grid that could pick up this event\r\n const onPointerUpEvent = (e: MouseEvent) => {\r\n if (itemBeingDraggedInfo.current) {\r\n itemBeingDraggedInfo.current = null;\r\n elementBeingDragged.current = null;\r\n\r\n onDragStatusChanged(false);\r\n }\r\n };\r\n\r\n window.addEventListener('mousemove', mouseMoveEventHandler, { passive: true });\r\n window.addEventListener('pointerup', onPointerUpEvent, { passive: true });\r\n\r\n return (): void => {\r\n if (mouseMoveEventTimer) {\r\n clearTimeout(mouseMoveEventTimer);\r\n }\r\n\r\n window.removeEventListener('mousemove', mouseMoveEventHandler);\r\n window.removeEventListener('pointerup', onPointerUpEvent);\r\n };\r\n }, [onDragStatusChanged]);\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nexport { BTGridContainerContext, BTGridContainerContextProvider };\r\n","import React, { useContext, useEffect, useState } from 'react';\nimport { Feature, FeatureFlags, getFeatureFlagsFromLocalStorage } from './features';\n\ninterface FeatureFlagContextReturn {\n featureIsEnabled: (feature: Feature) => boolean;\n}\n\nconst FeatureFlagContext = React.createContext(\n {} as FeatureFlagContextReturn,\n);\n\nexport const useFeatureFlags = (): FeatureFlagContextReturn => useContext(FeatureFlagContext);\n\nexport const FeatureFlagContextProvider: React.FC = (props) => {\n const [featureFlags, setFeatureFlags] = useState();\n\n // Get feature flags from local storage on mount\n useEffect(() => {\n const featureFlags = getFeatureFlagsFromLocalStorage();\n setFeatureFlags(featureFlags);\n }, []);\n\n const featureIsEnabled = (feature: Feature): boolean => {\n if (!featureFlags) {\n return false;\n }\n\n return featureFlags[feature] ?? false;\n };\n\n return (\n \n {props.children}\n \n );\n};\n","import React, { useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { getShortDateString } from '../../utils/dates';\r\nimport './ProjectInfoModal.scss';\r\nimport { NotificationPanelContext } from '../common-page-components/notification-panel/NotificationPanelContext';\r\nimport { ProjectApi } from '../../services';\r\n\r\ninterface Props {\r\n project: DetailProjectInfo;\r\n}\r\n\r\nconst ProjectInfoModal: React.FC = ({ project }) => {\r\n const { t } = useTranslation();\r\n\r\n const [projectImageBlobUrl, setProjectImageBlobUrl] = useState();\r\n\r\n const { showErrorNotification } = useContext(NotificationPanelContext);\r\n\r\n // The current project image name\r\n const currentProjectImageUri = useRef();\r\n\r\n useEffect(() => {\r\n const getProjectImageUrl = async () => {\r\n if (currentProjectImageUri.current !== project.imageUri) {\r\n if (project.imageUri) {\r\n // Fetch the latest project image if there is one\r\n try {\r\n const imageBlobUrl = await ProjectApi.getProjectImageBlobUrl(\r\n project.id,\r\n project.imageUri,\r\n );\r\n\r\n setProjectImageBlobUrl(imageBlobUrl);\r\n } catch (error) {\r\n showErrorNotification(t('general:error'), t('project:projectImageLoadError'));\r\n }\r\n } else {\r\n // Clear the blob url because the project image may be removed or never set\r\n setProjectImageBlobUrl(null);\r\n }\r\n\r\n currentProjectImageUri.current = project.imageUri;\r\n }\r\n };\r\n\r\n getProjectImageUrl();\r\n }, [project.id, project.imageUri, projectImageBlobUrl, showErrorNotification, t]);\r\n\r\n const streetAddressString = project.siteAddress\r\n ? [project.siteAddress.streetAddress, project.siteAddress.aptSuiteBldg]\r\n .filter((v) => v)\r\n .join(', ')\r\n : '';\r\n\r\n let cityStateString = project.siteAddress\r\n ? [project.siteAddress.city, project.siteAddress.stateOrRegion].filter((v) => v).join(', ')\r\n : '';\r\n\r\n if (project.siteAddress?.postalCode) {\r\n cityStateString = [cityStateString, project.siteAddress.postalCode].filter((v) => v).join(' ');\r\n }\r\n\r\n return (\r\n
    \r\n
    \r\n {projectImageBlobUrl ? (\r\n
    \r\n \"Project\"\r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n

    {project.name}

    \r\n\r\n {project.subtitle ?

    {project.subtitle}

    : <>}\r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n \r\n {streetAddressString || cityStateString || project.siteAddress?.country ? (\r\n
    \r\n {streetAddressString ?
    {streetAddressString}
    : <>}\r\n\r\n {cityStateString ?
    {cityStateString}
    : <>}\r\n\r\n {project.siteAddress?.country ? (\r\n
    {project.siteAddress.country}
    \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n ) : (\r\n <>{t('general:n/a')}\r\n )}\r\n
    \r\n
    \r\n \r\n {project.bidDueDate ? (\r\n
    {getShortDateString(project.bidDueDate)}
    \r\n ) : (\r\n <>{t('general:n/a')}\r\n )}\r\n
    \r\n
    \r\n \r\n
    {project.isHardBid ? 'Yes' : 'No'}
    \r\n
    \r\n
    \r\n \r\n {project.startDate || project.completionDate ? (\r\n
    \r\n {`${getShortDateString(project.startDate) || t('general:n/a')} - ${\r\n getShortDateString(project.completionDate) || t('general:n/a')\r\n }`}\r\n
    \r\n ) : (\r\n <>{t('general:n/a')}\r\n )}\r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n \r\n
    {project.owner || t('general:n/a')}
    \r\n
    \r\n
    \r\n \r\n {project.totalBuildingArea ? (\r\n
    {`${project.totalBuildingArea} ${project.totalBuildingAreaUnitOfMeasure}`}
    \r\n ) : (\r\n <>{t('general:n/a')}\r\n )}\r\n
    \r\n
    \r\n \r\n
    {project.architect || t('general:n/a')}
    \r\n
    \r\n
    \r\n \r\n {project.totalSiteArea ? (\r\n
    {`${project.totalSiteArea} ${project.totalSiteAreaUnitOfMeasure}`}
    \r\n ) : (\r\n <>{t('general:n/a')}\r\n )}\r\n
    \r\n
    \r\n
    \r\n );\r\n};\r\n\r\nexport default ProjectInfoModal;\r\n","import React, { useCallback, useState } from 'react';\r\nimport BTModal from '../../common-page-components/modal/BTModal';\r\nimport ProjectInfoModal from '../ProjectInfoModal';\r\n\r\ninterface ReturnValue {\r\n getProjectInfoJSX: () => JSX.Element;\r\n showProjectInfo: (project: DetailProjectInfo) => void;\r\n}\r\n\r\ninterface ProjectInfoModalState {\r\n isOpen: boolean;\r\n project: DetailProjectInfo | null;\r\n}\r\n\r\nconst useProject_Info = (): ReturnValue => {\r\n const [projectInfoModalState, setProjectInfoModalState] = useState({\r\n isOpen: false,\r\n project: null,\r\n });\r\n\r\n const showProjectInfo = useCallback((project: DetailProjectInfo) => {\r\n setProjectInfoModalState({ project: project, isOpen: true });\r\n }, []);\r\n\r\n const onProjectInfoModalClose = useCallback(() => {\r\n setProjectInfoModalState((curr) => ({\r\n ...curr,\r\n isOpen: false,\r\n }));\r\n }, [setProjectInfoModalState]);\r\n\r\n const getProjectInfoJSX = useCallback((): JSX.Element => {\r\n return projectInfoModalState.project ? (\r\n \r\n \r\n \r\n ) : (\r\n <>\r\n );\r\n }, [projectInfoModalState.project, projectInfoModalState.isOpen, onProjectInfoModalClose]);\r\n\r\n return { getProjectInfoJSX, showProjectInfo };\r\n};\r\n\r\nexport default useProject_Info;\r\n","import React, { useContext, useEffect, useRef } from 'react';\nimport { BTGridContainerContext } from './grid-container/BTGridContainerContext';\n\n// NOTE: This component is responsible for managing the \"ghost\" element that we move alongside the mouse\n// when the user is dragging and dropping something\nconst BTGridDraggedElement: React.FC = () => {\n const { itemBeingDraggedInfo, elementBeingDragged } = useContext(BTGridContainerContext);\n\n const clonedDraggedElement = useRef(null);\n\n useEffect(() => {\n let mouseMoveEventTimer: NodeJS.Timeout | null;\n\n const mouseMoveEventHandler = (e: MouseEvent): void => {\n if (mouseMoveEventTimer) {\n return;\n }\n\n // Only update things every so often since mouse events come in fast and furious\n mouseMoveEventTimer = setTimeout(() => {\n if (itemBeingDraggedInfo.current) {\n const elementBeingDraggedBoundingRect = elementBeingDragged.current!.getBoundingClientRect();\n\n // Add the ghost element to the DOM if it isn't there already\n if (!clonedDraggedElement.current) {\n const ghostElement = elementBeingDragged.current!.cloneNode(true) as HTMLElement;\n\n ghostElement.classList.add(\n 'draggedRow',\n `draggedRow-${itemBeingDraggedInfo.current.direction}`,\n );\n\n ghostElement.style.width = elementBeingDraggedBoundingRect.width + 'px';\n\n // Set the initial position at the origin of the element we copied.\n // NOTE: The translateZ code will cause this element to get put on its own rendering layer,\n // so animating it with transforms will be super smooth.\n if (itemBeingDraggedInfo.current.direction === 'vertical') {\n ghostElement.style.transform = `translateZ(0) translateY(${\n elementBeingDragged.current!.getBoundingClientRect().top -\n elementBeingDraggedBoundingRect.height / 2 +\n 'px'\n })`;\n\n ghostElement.style.top = '0';\n ghostElement.style.left = elementBeingDraggedBoundingRect.left + 'px';\n } else {\n ghostElement.style.transform = `translateZ(0) translateX(${\n elementBeingDragged.current!.getBoundingClientRect().left -\n elementBeingDraggedBoundingRect.height / 2 +\n 'px'\n })`;\n\n ghostElement.style.top = elementBeingDraggedBoundingRect.top + 25 + 'px';\n ghostElement.style.left = '0';\n }\n\n document.body.appendChild(ghostElement);\n\n // NOTE: We use fixed position / transform, for performance reasons\n ghostElement.style.position = 'fixed';\n ghostElement.style.opacity = '1';\n ghostElement.style.zIndex = '9999999';\n ghostElement.style.userSelect = 'none';\n ghostElement.style.transitionDuration = '10ms';\n\n clonedDraggedElement.current = ghostElement;\n }\n\n // NOTE: This is just relaive to the viewport, since the element we're animating is a fixed position, which\n // is also relative to the viewport\n if (itemBeingDraggedInfo.current.direction === 'vertical') {\n const mouseVerticalOffset = e.y;\n\n // NOTE: We need some distance between the mouse cursor and the element being dragged, so the mouse can\n // still trigger events on elements underneath the floating ghost element\n clonedDraggedElement.current.style.transform = `translateZ(0) translateY(${\n mouseVerticalOffset + 25 + 'px'\n })`;\n } else {\n const mouseHorizontalOffset = e.x;\n\n // NOTE: We need some distance between the mouse cursor and the element being dragged, so the mouse can\n // still trigger events on elements underneath the floating ghost element\n clonedDraggedElement.current.style.transform = `translateZ(0) translateX(${\n mouseHorizontalOffset + 50 + 'px'\n })`;\n }\n } else {\n clonedDraggedElement.current = null;\n }\n mouseMoveEventTimer = null;\n }, 10);\n };\n\n // We watch for the pointer up event on the window, in case the user released the pointer but wasn't over\n // any of parts of the grid that could pick up this event\n const onPointerUpEvent = (e: MouseEvent) => {\n if (clonedDraggedElement.current) {\n document.body.removeChild(clonedDraggedElement.current);\n\n clonedDraggedElement.current = null;\n }\n };\n\n window.addEventListener('mousemove', mouseMoveEventHandler, { passive: true });\n window.addEventListener('pointerup', onPointerUpEvent, { passive: true });\n\n return (): void => {\n if (mouseMoveEventTimer) {\n clearTimeout(mouseMoveEventTimer);\n }\n\n window.removeEventListener('mousemove', mouseMoveEventHandler);\n window.removeEventListener('pointerup', onPointerUpEvent);\n };\n }, [elementBeingDragged, itemBeingDraggedInfo]);\n\n return <>;\n};\n\nexport default BTGridDraggedElement;\n","const getElementOffset = (el: HTMLElement): { left: number; top: number } => {\r\n const rect = el.getBoundingClientRect(),\r\n scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,\r\n scrollTop = window.pageYOffset || document.documentElement.scrollTop;\r\n return { top: rect.top + scrollTop, left: rect.left + scrollLeft };\r\n};\r\n\r\nexport { getElementOffset };\r\n","import React from 'react';\r\nimport { Observable } from 'rxjs';\r\nimport { useObservable } from '../../../hooks/observables/useObservable';\r\n\r\n// Yo dawg, I heard you like contexts...\r\ninterface BTContextMenuContextInterface {\r\n contextMenuOpen$: Observable;\r\n openContextMenu: () => void;\r\n}\r\n\r\nconst BTContextMenuContext = React.createContext(\r\n {} as BTContextMenuContextInterface,\r\n);\r\n\r\nconst BTContextMenuContextProvider: React.FC = ({ children }) => {\r\n const [contextMenuOpen$, openContextMenu] = useObservable();\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nexport { BTContextMenuContext, BTContextMenuContextProvider };\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\r\nimport { Dropdown, DropdownItem, DropdownMenu } from 'reactstrap';\r\nimport './BTContextMenu.scss';\r\nimport { BTContextMenuContext } from './BTContextMenuContext';\r\n\r\ninterface Props {\r\n // A flag that lets us specify whether right-clicking an input should trigger the context menu.\r\n // This is useful for customizing behavior when we have a context menu on something that has children inputs\r\n // that should work in a default way when right clicked (ie. so the user can copy, paste, etc.).\r\n shouldAllowInputToTriggerContextMenu: boolean;\r\n items: BTContextMenuItem[];\r\n // An optional JSX element that holds components.\r\n // This is useful for when we want to provide rendered data from another component instead of\r\n // programatically providing static dropdown item data.\r\n additionalItemsJSX?: JSX.Element;\r\n children: JSX.Element;\r\n}\r\n\r\nconst BTContextMenu: React.FC = ({\r\n shouldAllowInputToTriggerContextMenu,\r\n items,\r\n children,\r\n additionalItemsJSX,\r\n}) => {\r\n const { openContextMenu, contextMenuOpen$ } = useContext(BTContextMenuContext);\r\n\r\n const contextMenuContainerElement = useRef();\r\n\r\n const [contextMenuDropdownIsOpen, setContextMenuDropdownIsOpen] = useState(false);\r\n\r\n const [lastClickedCoordinates, setLastClickedCoordinates] = useState<{ x: number; y: number }>({\r\n x: 0,\r\n y: 0,\r\n });\r\n\r\n // Listen for any updates that any other context menu was opened on the page\r\n useEffect(() => {\r\n const subscription = contextMenuOpen$.subscribe(() => {\r\n // We want to always close the dropdown when this happens, but will reopen it right after on the most recently\r\n // opened context menu component\r\n setContextMenuDropdownIsOpen(false);\r\n });\r\n\r\n return () => subscription.unsubscribe();\r\n }, [contextMenuOpen$]);\r\n\r\n const getItemsForDisplay = useCallback((): JSX.Element => {\r\n if (!items.length && !additionalItemsJSX?.props?.children?.length) {\r\n return <>;\r\n }\r\n\r\n const itemsToDisplay = [...items];\r\n\r\n // If the first or last item is a divider, remove it -- if we have multiple subsequent dividers on either end,\r\n // we need to be better programmers elsewhere\r\n if (itemsToDisplay[0].isDivider) {\r\n itemsToDisplay.shift();\r\n }\r\n\r\n const lastItem = itemsToDisplay[itemsToDisplay.length - 1];\r\n if (lastItem && lastItem.isDivider) {\r\n itemsToDisplay.pop();\r\n }\r\n\r\n return (\r\n <>\r\n {itemsToDisplay.map((currContextMenuItem) => {\r\n return !currContextMenuItem.isDivider ? (\r\n {\r\n if (currContextMenuItem.onClick) {\r\n currContextMenuItem.onClick();\r\n }\r\n }}\r\n icon={currContextMenuItem.icon}\r\n text={currContextMenuItem.text}\r\n secondaryText={currContextMenuItem.secondaryText}\r\n />\r\n ) : (\r\n \r\n );\r\n })}\r\n\r\n {additionalItemsJSX ? additionalItemsJSX : <>}\r\n \r\n );\r\n }, [additionalItemsJSX, items]);\r\n\r\n return useMemo(() => {\r\n return (\r\n {\r\n if (e) {\r\n contextMenuContainerElement.current = e;\r\n }\r\n }}\r\n onContextMenu={(e) => {\r\n // If the element that was right-clicked was an input element, we want to do nothing and let the event bubble up\r\n const targetIsInputElement = (e.target as HTMLElement).matches('input, select');\r\n if (!shouldAllowInputToTriggerContextMenu && targetIsInputElement) {\r\n return;\r\n }\r\n\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n // Persist the event so it doesn't get reused by React\r\n e.persist();\r\n\r\n // We want to set coordinates of the right click, so we can open the dropdown at that position and make it feel more responsive to the user\r\n // than opening the dropdown in a static position\r\n\r\n // NOTE: getBoundingClientRect() / clientX / clientY return calculated offset values relative to the viewport\r\n const boundsOfDropdownContainer = contextMenuContainerElement.current!.getBoundingClientRect()!;\r\n const clickCoordinate_X = e.clientX;\r\n const clickCoordinate_Y = e.clientY;\r\n\r\n const xCoordinate = clickCoordinate_X - boundsOfDropdownContainer.left;\r\n\r\n setLastClickedCoordinates({\r\n x: xCoordinate,\r\n y: clickCoordinate_Y - boundsOfDropdownContainer.top,\r\n });\r\n\r\n // Let the shared context know that a new context menu was opened, so any other open context menus can close\r\n openContextMenu();\r\n\r\n // Open this context menu now that others have closed\r\n setContextMenuDropdownIsOpen(true);\r\n }}\r\n >\r\n {/* Don't display the dropdown if we don't have any items to display */}\r\n {items.length > 0 ? (\r\n {\r\n setContextMenuDropdownIsOpen((currValue) => !currValue);\r\n }}\r\n >\r\n \r\n {getItemsForDisplay()}\r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {/* Output any children elements since this component acts as a wrapper around other code */}\r\n {children}\r\n
    \r\n );\r\n }, [\r\n contextMenuDropdownIsOpen,\r\n getItemsForDisplay,\r\n lastClickedCoordinates.x,\r\n lastClickedCoordinates.y,\r\n openContextMenu,\r\n children,\r\n items.length,\r\n shouldAllowInputToTriggerContextMenu,\r\n ]);\r\n};\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\r\ninterface BTDropdownMenuItemProps extends BTContextMenuItem {}\r\n\r\nexport const BTDropdownMenuItem: React.FC = ({\r\n id,\r\n onClick,\r\n icon,\r\n text,\r\n secondaryText,\r\n isDivider,\r\n}) => {\r\n return !isDivider ? (\r\n {\r\n if (onClick) {\r\n onClick();\r\n }\r\n }}\r\n >\r\n {icon ? (\r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {text}\r\n\r\n {(secondaryText?.length ?? 0) > 0 ? (\r\n {secondaryText}\r\n ) : (\r\n <>\r\n )}\r\n \r\n ) : (\r\n \r\n );\r\n};\r\n\r\nexport default BTContextMenu;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport { random } from 'lodash';\r\nimport React, { useContext, useEffect, useRef, useState } from 'react';\r\nimport { Subscription } from 'rxjs';\r\nimport { BTGeneralContext } from '../../general-contexts/BTGeneralContext';\r\nimport { BTGridContainerContext } from '../grid-container/BTGridContainerContext';\r\n\r\ninterface BTGridRowCellProps {\r\n collapseDirection: CollapseDirection | null;\r\n collapsibleIconJSXElementFactory: CollapsibleIconJSXElementFactoryType | undefined;\r\n currCell: BTGridCell;\r\n rowHeight: number | string;\r\n gridSectionId: string;\r\n cellIndex: number;\r\n isCollapsed: boolean;\r\n isCollapsibleTrigger: boolean;\r\n isHovered: boolean;\r\n isPlaceholderForHorizontalFrozenCell: boolean;\r\n isPlaceholderForVerticalFrozenCell: boolean;\r\n isPrimaryGridRow: boolean;\r\n isSelected: boolean;\r\n elementKey: number;\r\n rowGroupingLevel: number;\r\n rowNumber: number;\r\n testId: string;\r\n}\r\n\r\nconst BTGridRowCell: React.FC = ({\r\n collapseDirection,\r\n collapsibleIconJSXElementFactory,\r\n currCell,\r\n rowHeight,\r\n gridSectionId,\r\n cellIndex,\r\n isCollapsed,\r\n isCollapsibleTrigger,\r\n isHovered,\r\n isPlaceholderForHorizontalFrozenCell,\r\n isPlaceholderForVerticalFrozenCell,\r\n isPrimaryGridRow,\r\n isSelected,\r\n elementKey,\r\n rowGroupingLevel,\r\n rowNumber,\r\n testId,\r\n}) => {\r\n const frozenCell_InitialXOffset = useRef(null);\r\n const frozenCell_InitialYOffset = useRef(null);\r\n\r\n // NOTE: It is assumed that each row will only have a single frozen cell of each type at most\r\n const frozenCellRef_X = useRef();\r\n const frozenCellRef_Y = useRef();\r\n\r\n const [pageScrollOffset_X, setPageScrollOffset_X] = useState(0);\r\n const [pageScrollOffset_Y, setPageScrollOffset_Y] = useState(0);\r\n\r\n const cellIsFrozen_X = frozenCellShouldMove_X(\r\n currCell,\r\n frozenCell_InitialXOffset.current ?? 0,\r\n pageScrollOffset_X,\r\n );\r\n\r\n const cellIsFrozen_Y = frozenCellShouldMove_Y(\r\n currCell,\r\n frozenCell_InitialYOffset.current ?? 0,\r\n pageScrollOffset_Y,\r\n );\r\n\r\n const { easterEgg_BoogieNights, pageScroll_X$, pageScroll_Y$ } = useContext(BTGeneralContext);\r\n\r\n const { onSetCellRef } = useContext(BTGridContainerContext);\r\n\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n // If the row contains frozen cells, update the state variables when the offset changes\r\n if (currCell.frozenOnHorizontalScroll) {\r\n allSubscriptions.add(\r\n pageScroll_X$.subscribe((newOffset) => {\r\n setPageScrollOffset_X(newOffset);\r\n }),\r\n );\r\n }\r\n\r\n if (currCell.frozenOnVerticalScroll) {\r\n allSubscriptions.add(\r\n pageScroll_Y$.subscribe((newOffset) => {\r\n // NOTE: We do not offset setting code for Y offset, since we won't\r\n // have that many cells that float vertically\r\n setPageScrollOffset_Y(newOffset);\r\n }),\r\n );\r\n }\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [\r\n currCell.frozenOnHorizontalScroll,\r\n currCell.frozenOnVerticalScroll,\r\n pageScroll_X$,\r\n pageScroll_Y$,\r\n ]);\r\n\r\n const getIndentCSSClass = (): string => {\r\n return isPrimaryGridRow && rowGroupingLevel >= 0 ? `indent-${rowGroupingLevel}` : '';\r\n };\r\n\r\n const getCollapsibleIconJSX = (): JSX.Element => {\r\n // We need to position the chevron icon based on the collapse direction\r\n const isChevronRotated = collapseDirection === 'up' ? !isCollapsed : isCollapsed;\r\n\r\n const innerElement: JSX.Element = (\r\n \r\n \r\n \r\n );\r\n\r\n if (collapsibleIconJSXElementFactory) {\r\n return collapsibleIconJSXElementFactory(innerElement);\r\n }\r\n return innerElement;\r\n };\r\n\r\n const cellStyle: React.CSSProperties = getCellStyle({\r\n currCell,\r\n easterEgg_BoogieNights,\r\n frozenCell_InitialXOffset: frozenCell_InitialXOffset.current ?? 0,\r\n frozenCell_InitialYOffset: frozenCell_InitialYOffset.current ?? 0,\r\n isPlaceholderForHorizontalFrozenCell,\r\n isPlaceholderForVerticalFrozenCell,\r\n pageScrollOffset_X,\r\n pageScrollOffset_Y,\r\n rowHeight,\r\n });\r\n\r\n if (isPlaceholderForHorizontalFrozenCell) {\r\n const leftOffsetOfNonPlaceholderElement = frozenCellRef_X.current?.offsetLeft;\r\n const leftOffset = leftOffsetOfNonPlaceholderElement ?? 0;\r\n\r\n cellStyle.left = leftOffset;\r\n cellStyle.position = 'absolute';\r\n\r\n // If the cell isn't actively being floated, do not display it.\r\n // NOTE: We use opacity here so things can transition nicely, whereas using the display property can cause jerkiness.\r\n if (!cellIsFrozen_X) {\r\n cellStyle.opacity = 0;\r\n cellStyle.zIndex = -1;\r\n }\r\n }\r\n\r\n if (isPlaceholderForVerticalFrozenCell) {\r\n // NOTE: For vertical cells, we don't have to worry about an offset because there won't be elements above\r\n // or below any cells in a row\r\n cellStyle.position = 'absolute';\r\n\r\n // If the cell isn't actively being floated, do not display it.\r\n // NOTE: We use opacity here so things can transition nicely, whereas using the display property can cause jerkiness.\r\n if (!cellIsFrozen_Y) {\r\n cellStyle.opacity = 0;\r\n cellStyle.zIndex = -1;\r\n }\r\n }\r\n\r\n const cellContentToRender =\r\n isCollapsed && currCell.cellContentWhenCollapsed\r\n ? currCell.cellContentWhenCollapsed\r\n : currCell.cellContent;\r\n\r\n // NOTE: we're trying to check if the cell to render is not an empty cell (something like `<>`)\r\n // however, `<>` would fail the first check, since it's type is a React.Fragment, so we\r\n // additionally check its children as a basic validation that it will render something.\r\n // this will be true for a `
    `, but this is mainly to guard against Fragments.\r\n const doesCellDisplayContent =\r\n (cellContentToRender?.type ?? cellContentToRender) !== React.Fragment ||\r\n React.Children.count(cellContentToRender?.props?.children ?? []) > 0;\r\n\r\n const dataAttributes: Record = {};\r\n\r\n if (currCell.dataAttributes) {\r\n Object.keys(currCell.dataAttributes).forEach((currKey) => {\r\n dataAttributes[`data-${currKey}`] = currCell.dataAttributes![currKey];\r\n });\r\n }\r\n\r\n if (currCell.cellTriggersBTPopover) {\r\n dataAttributes['data-triggers-popover'] = '';\r\n }\r\n\r\n return (\r\n {\r\n if (!el) {\r\n return;\r\n }\r\n\r\n // Set the initial left offsets of the frozen cells, for use with calculating its position\r\n // when the user scrolls\r\n if (currCell.frozenOnHorizontalScroll && frozenCell_InitialXOffset.current === null) {\r\n // Only set a reference to the original cell, not the placeholder one\r\n if (!isPlaceholderForHorizontalFrozenCell) {\r\n frozenCellRef_X.current = el;\r\n }\r\n\r\n // NOTE: The bounding rectangle measurements are the element relative to the viewport so we add the scroll offset in\r\n // to get the true offset\r\n frozenCell_InitialXOffset.current =\r\n (el.getBoundingClientRect().left ?? 0) + pageScrollOffset_X;\r\n }\r\n\r\n if (currCell.frozenOnVerticalScroll && frozenCell_InitialYOffset.current === null) {\r\n frozenCellRef_Y.current = el;\r\n\r\n // NOTE: The bounding rectangle measurements are the element relative to the viewport so we add the scroll offset in\r\n // to get the true offset\r\n frozenCell_InitialYOffset.current =\r\n (el.getBoundingClientRect().top ?? 0) + pageScrollOffset_Y;\r\n }\r\n\r\n // Set the cell ref for use with the grid container\r\n onSetCellRef({ gridSectionId, element: el, rowNumber });\r\n }}\r\n className={`cellColumn ${currCell.className || ''} ${\r\n isPlaceholderForHorizontalFrozenCell && cellIsFrozen_X ? 'frozenOnHorizontalScroll' : ''\r\n } ${isPlaceholderForVerticalFrozenCell && cellIsFrozen_Y ? 'frozenOnVerticalScroll' : ''}\r\n ${\r\n easterEgg_BoogieNights\r\n ? 'ee-boogie-nights ' +\r\n getCellClass(\r\n currCell.cellWidth,\r\n currCell.cellHorizontalAlignment,\r\n currCell.cellVerticalAlignment,\r\n 'none',\r\n isHovered,\r\n isSelected,\r\n currCell.trimTextOnOverflow ?? false,\r\n )\r\n : getCellClass(\r\n currCell.cellWidth,\r\n currCell.cellHorizontalAlignment,\r\n currCell.cellVerticalAlignment,\r\n currCell.cellBackgroundColor,\r\n isHovered,\r\n isSelected,\r\n currCell.trimTextOnOverflow ?? false,\r\n )\r\n } ${\r\n easterEgg_BoogieNights ? '' : getAdditionalStylesClasses(currCell.cellAdditionalStyles)\r\n } ${isCollapsed ? getAdditionalStylesClasses(currCell.cellAdditionalCollapseStyles) : ''} ${\r\n !isCollapsed ? getAdditionalStylesClasses(currCell.cellAdditionalUncollapseStyles) : ''\r\n }`.trim()}\r\n style={cellStyle}\r\n onMouseEnter={\r\n doesCellDisplayContent && currCell.onCellMouseEnter\r\n ? (e) => {\r\n currCell.onCellMouseEnter!(e);\r\n }\r\n : undefined\r\n }\r\n onMouseLeave={\r\n doesCellDisplayContent && currCell.onCellMouseLeave\r\n ? (e) => {\r\n currCell.onCellMouseLeave!(e);\r\n }\r\n : undefined\r\n }\r\n {...dataAttributes}\r\n >\r\n \r\n {isCollapsibleTrigger && cellIndex === 0 && (\r\n {getCollapsibleIconJSX()} \r\n )}\r\n\r\n {cellContentToRender}\r\n
    \r\n
    \r\n );\r\n};\r\n\r\nconst frozenCellShouldMove_X = (\r\n cell: BTGridCell,\r\n frozenCell_InitialXOffset: number,\r\n pageScrollOffset_X: number,\r\n) => {\r\n return (\r\n cell?.frozenOnHorizontalScroll &&\r\n frozenCell_InitialXOffset &&\r\n frozenCell_InitialXOffset! <= pageScrollOffset_X\r\n );\r\n};\r\n\r\nconst frozenCellShouldMove_Y = (\r\n cell: BTGridCell,\r\n frozenCell_InitialYOffset: number,\r\n pageScrollOffset_Y: number,\r\n) => {\r\n if (cell?.frozenOnVerticalScroll && frozenCell_InitialYOffset) {\r\n if (cell.frozenOnVerticalScroll.anchorElementSelector) {\r\n // Get the current position of the anchor element, so we can check the position of the frozen\r\n // cell relative to it (in case the anchor element moved for whatever reason (ex. a navbar\r\n // that resizes when the user scrolls))\r\n const anchorElementOffset =\r\n (document\r\n .querySelector(cell.frozenOnVerticalScroll.anchorElementSelector)\r\n ?.getBoundingClientRect()?.bottom ?? 0) + pageScrollOffset_Y;\r\n\r\n if (frozenCell_InitialYOffset <= anchorElementOffset) {\r\n return true;\r\n }\r\n } else if (frozenCell_InitialYOffset <= pageScrollOffset_Y) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\nconst getCellClass = (\r\n cellWidthType: BTGridCellWidths,\r\n cellHorizontalAlignment: BTGridCellHorizontalAlignments | undefined,\r\n cellVerticalAlignment: BTGridCellVerticalAlignments | undefined,\r\n cellBackgroundColor: BTGridCellBackgroundColors | undefined,\r\n isHovered: boolean,\r\n isSelected: boolean,\r\n trimTextOnOverflow: boolean,\r\n): string => {\r\n const returnValue: string[] = [];\r\n\r\n returnValue.push(`cellWidth-${cellWidthType}`);\r\n\r\n switch (cellHorizontalAlignment) {\r\n case 'center':\r\n returnValue.push('text-center');\r\n break;\r\n\r\n case 'right':\r\n returnValue.push('text-right');\r\n break;\r\n\r\n case 'left':\r\n default:\r\n returnValue.push('text-left');\r\n break;\r\n }\r\n\r\n switch (cellVerticalAlignment) {\r\n case 'top':\r\n returnValue.push('align-items-start');\r\n break;\r\n\r\n case 'bottom':\r\n returnValue.push('align-items-end');\r\n break;\r\n\r\n case 'center':\r\n default:\r\n returnValue.push('align-items-center');\r\n break;\r\n }\r\n\r\n if (trimTextOnOverflow) {\r\n returnValue.push('overflowEllipses');\r\n }\r\n\r\n // If the cell background color is specified, use it, otherwise set it to white if the row isn't hovered\r\n // or selected, in which case it will have a different background color set\r\n if (cellBackgroundColor && cellBackgroundColor !== 'none') {\r\n returnValue.push(`backgroundColor-${cellBackgroundColor}`);\r\n } else if (!isHovered && !isSelected) {\r\n returnValue.push('backgroundColor-white');\r\n }\r\n\r\n return returnValue.join(' ');\r\n};\r\n\r\nconst getHorizontalAlignmentCSSClass_FlexDisplay = (\r\n cellHorizontalAlignment: BTGridCellHorizontalAlignments | undefined,\r\n): string => {\r\n switch (cellHorizontalAlignment) {\r\n case 'center':\r\n return 'justify-content-center';\r\n\r\n case 'right':\r\n return 'justify-content-end';\r\n\r\n case 'left':\r\n default:\r\n return 'justify-content-start';\r\n }\r\n};\r\n\r\nconst generateRandomColor = (): string => {\r\n const colors = [\r\n 'FFA726',\r\n '00C853',\r\n 'EEFF41',\r\n '00E5FF',\r\n '01579B',\r\n 'E65100',\r\n '4527A0',\r\n 'F50057',\r\n '00BCD4',\r\n ];\r\n return `#${colors[random(0, colors.length - 1)]}`;\r\n};\r\n\r\nexport const getCellStyle = (data: {\r\n currCell: BTGridCell | null;\r\n easterEgg_BoogieNights: boolean;\r\n frozenCell_InitialXOffset: number;\r\n frozenCell_InitialYOffset: number;\r\n isPlaceholderForHorizontalFrozenCell: boolean;\r\n isPlaceholderForVerticalFrozenCell: boolean;\r\n pageScrollOffset_X: number;\r\n pageScrollOffset_Y: number;\r\n rowHeight: string | number;\r\n}): Dictionary => {\r\n let minHeight: string | number = '';\r\n\r\n if (typeof data.rowHeight === 'string' && (data.rowHeight as string).length) {\r\n minHeight = data.rowHeight;\r\n } else if (typeof data.rowHeight === 'number') {\r\n minHeight = `${data.rowHeight}px`;\r\n }\r\n\r\n let returnValue: Dictionary = {};\r\n\r\n if (data.currCell) {\r\n if (\r\n data.isPlaceholderForHorizontalFrozenCell &&\r\n frozenCellShouldMove_X(\r\n data.currCell,\r\n data.frozenCell_InitialXOffset ?? 0,\r\n data.pageScrollOffset_X,\r\n )\r\n ) {\r\n const amountToMoveFrozenCell = Math.floor(\r\n Math.max(0, data.pageScrollOffset_X - data.frozenCell_InitialXOffset!),\r\n );\r\n\r\n // NOTE: We shrink the scale of the frozen cell a little, since there are likely to be many horizontally frozen cells\r\n // in subsequent rows and we want to be able to see the box shadow around each cell clearly.\r\n // NOTE: We use translateZ so the element gets put on its own compositor layer, for performance.\r\n returnValue['transform'] = `translateX(${\r\n amountToMoveFrozenCell + 15\r\n }px) translateY(-1px) translateZ(0) scale(.98)`;\r\n }\r\n\r\n if (\r\n data.isPlaceholderForVerticalFrozenCell &&\r\n frozenCellShouldMove_Y(\r\n data.currCell,\r\n data.frozenCell_InitialYOffset ?? 0,\r\n data.pageScrollOffset_Y,\r\n )\r\n ) {\r\n let anchorOffset = 0;\r\n\r\n if (data.currCell?.frozenOnVerticalScroll?.anchorElementSelector) {\r\n anchorOffset =\r\n document\r\n .querySelector(data.currCell.frozenOnVerticalScroll.anchorElementSelector)\r\n ?.getBoundingClientRect().bottom ?? 0;\r\n }\r\n\r\n const amountToMoveFrozenCell = Math.floor(\r\n Math.max(0, data.pageScrollOffset_Y - data.frozenCell_InitialYOffset! + anchorOffset) + 15,\r\n );\r\n\r\n // NOTE: We use translateZ so the element gets put on its own compositor layer, for performance\r\n returnValue['transform'] = `translateY(${amountToMoveFrozenCell}px) translateZ(0)`;\r\n }\r\n }\r\n\r\n if (data.easterEgg_BoogieNights) {\r\n returnValue = {\r\n ...returnValue,\r\n background: `linear-gradient(-45deg, ${generateRandomColor()}, ${generateRandomColor()}, ${generateRandomColor()}, ${generateRandomColor()})`,\r\n borderRadius: '10px',\r\n color: 'white',\r\n minHeight: minHeight.toString(),\r\n maxHeight: minHeight.toString(),\r\n };\r\n } else {\r\n returnValue = {\r\n ...returnValue,\r\n minHeight: minHeight.toString(),\r\n // NOTE: 'auto' is not a valid value for maxHeight\r\n maxHeight: minHeight === 'auto' ? 'none' : minHeight.toString(),\r\n };\r\n }\r\n\r\n return returnValue;\r\n};\r\n\r\nexport const getAdditionalStylesClasses = (\r\n cellAdditionalStyles: BTGridCellStyles[] | undefined,\r\n): string => {\r\n return cellAdditionalStyles && cellAdditionalStyles.length\r\n ? cellAdditionalStyles.map((v) => `bt-${v}`).join(' ')\r\n : '';\r\n};\r\n\r\nexport default BTGridRowCell;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Collapse } from 'reactstrap';\nimport { Subscription } from 'rxjs';\nimport { getElementOffset } from '../../../../utils/dom';\nimport { normalizeNullOrUndefined } from '../../../../utils/general';\nimport { areTrimmedStringsEqual } from '../../../../utils/strings';\nimport BTContextMenu from '../../context-menu/BTContextMenu';\nimport { BTGeneralContext } from '../../general-contexts/BTGeneralContext';\nimport { BTGridContainerContext } from '../grid-container/BTGridContainerContext';\nimport './BTGridRow.scss';\nimport BTGridRowCell, { getAdditionalStylesClasses, getCellStyle } from './BTGridRowCell';\n\ninterface Props {\n btGridRow: BTGridRowBase;\n correspondingPrimaryGridSectionGridRow: BTGridRowPrimary;\n testId: string;\n className?: string;\n gridSectionId: string;\n collapseOrSelectGroupingKey: string;\n rowNumber: number;\n isReadOnly: boolean;\n shouldRespondToMouseEvents: boolean;\n}\n\nconst BTGridRow: React.FC = ({\n btGridRow,\n correspondingPrimaryGridSectionGridRow,\n testId,\n className,\n gridSectionId,\n collapseOrSelectGroupingKey,\n rowNumber,\n isReadOnly,\n shouldRespondToMouseEvents,\n}) => {\n const { t } = useTranslation();\n\n const {\n collapsedRowsChange$,\n onRowCheckboxClick,\n onRowClick,\n onRowMouseEnter,\n onRowMouseLeave,\n onSetCellRef,\n rerenderStatus,\n rowMouseEnter$,\n rowMouseLeave$,\n selectedRowsChange$,\n rowHeightCollections,\n itemBeingDraggedInfo,\n dragStatusChanged$,\n elementBeingDragged,\n onDragStatusChanged,\n onItemsReordered,\n lastMouseCoordinates,\n } = useContext(BTGridContainerContext);\n\n const { easterEgg_BoogieNights, pageScroll_X$, pageScroll_Y$ } = useContext(BTGeneralContext);\n\n const rowHeightCollectionForGridSection = rowHeightCollections.current.find(\n (v) => v.gridSectionId === gridSectionId,\n );\n\n const rowHeight = rowHeightCollectionForGridSection?.rowHeights[rowNumber] || '';\n\n const previousRerenderId = useRef(null);\n const dragAndDropResponseTimeout = useRef(null);\n\n const [isHovered, setIsHovered] = useState(false);\n const [isSelected, setIsSelected] = useState(false);\n const [isActiveDragAndDropTarget_Bottom, setIsActiveDragAndDropTarget_Bottom] = useState(\n false,\n );\n const [isActiveDragAndDropTarget_Top, setIsActiveDragAndDropTarget_Top] = useState(\n false,\n );\n const [isActiveDragAndDropTarget_Left, setIsActiveDragAndDropTarget_Left] = useState(\n false,\n );\n const [isActiveDragAndDropTarget_Right, setIsActiveDragAndDropTarget_Right] = useState(\n false,\n );\n\n const [isInvalidDropTarget, setIsInvalidDropTarget] = useState(false);\n\n // Tells the row whether it is in a \"collapsed\" state (meaning it is a collapsible trigger and will have \"children\" rows underneath it)\n const [isCollapsed, setIsCollapsed] = useState(false);\n\n // Tells the row whether it should be visible.\n // NOTE: This defaults to true initially, as the grid depends on it being visible so initial calculations can be performed.\n const [isVisible, setIsVisible] = useState(true);\n\n // Update the previous rerender ID when the rerender ID changes\n useEffect(() => {\n if (previousRerenderId.current !== rerenderStatus?.rerenderId) {\n previousRerenderId.current = rerenderStatus?.rerenderId || '';\n }\n }, [rerenderStatus?.rerenderId]);\n\n const updateCollapseStateVariable = useCallback(\n (newCollapsedItems: GridSectionCollapsedRowsMapping[]) => {\n setIsCollapsed(\n newCollapsedItems.some(\n (v) =>\n v.groupingKey === collapseOrSelectGroupingKey &&\n v.rowMetadataMappings.some(\n (m) =>\n normalizeNullOrUndefined(m.rowGroupingInfo.groupingKey1) ===\n normalizeNullOrUndefined(\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey1,\n ) &&\n normalizeNullOrUndefined(m.rowGroupingInfo.groupingKey2) ===\n normalizeNullOrUndefined(\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey2,\n ),\n ),\n ),\n );\n },\n [\n collapseOrSelectGroupingKey,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey1,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey2,\n ],\n );\n\n const updateVisibleStateVariable = useCallback(\n (newCollapsedItems: GridSectionCollapsedRowsMapping[]) => {\n setIsVisible(() => {\n // If we are recalculating grid dimensions we will want rows to be expanded\n if (rerenderStatus !== null) {\n return true;\n }\n\n const allGlobalTriggerKeys = newCollapsedItems\n .flatMap((v) => v.rowMetadataMappings)\n .map((v) => v.rowGroupingInfo.globalCollapseTriggerKey)\n .filter((v) => v);\n\n if (\n allGlobalTriggerKeys.includes(\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseResponseKey ?? null,\n )\n ) {\n return false;\n }\n\n // Check to see if a root element that shares the same groupingKey1 as the current row is collapsed\n const rootLevelItemIsCollapsed = newCollapsedItems.some(\n (v) =>\n v.groupingKey === collapseOrSelectGroupingKey &&\n v.rowMetadataMappings.some(\n (m) =>\n normalizeNullOrUndefined(m.rowGroupingInfo.groupingKey1) ===\n normalizeNullOrUndefined(\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey1 || null,\n ) && normalizeNullOrUndefined(m.rowGroupingInfo.groupingKey2) === null,\n null,\n ),\n );\n\n // If the root element is collapsed, only collapse this row if it isn't the same as the root element row\n if (\n rootLevelItemIsCollapsed &&\n normalizeNullOrUndefined(\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey2,\n ) !== null\n ) {\n return false;\n }\n\n // Look for collapsed items that share both grouping keys but that aren't collapsible triggers\n if (\n newCollapsedItems.some(\n (v) =>\n v.groupingKey === collapseOrSelectGroupingKey &&\n !correspondingPrimaryGridSectionGridRow.isCollapsibleTrigger &&\n v.rowMetadataMappings.some(\n (m) =>\n normalizeNullOrUndefined(m.rowGroupingInfo.groupingKey1) ===\n normalizeNullOrUndefined(\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey1 || null,\n ) &&\n normalizeNullOrUndefined(m.rowGroupingInfo.groupingKey2) ===\n normalizeNullOrUndefined(\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey2 || null,\n ),\n ),\n )\n ) {\n return false;\n }\n\n return true;\n });\n },\n [\n collapseOrSelectGroupingKey,\n correspondingPrimaryGridSectionGridRow.isCollapsibleTrigger,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseResponseKey,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey1,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey2,\n rerenderStatus,\n ],\n );\n\n // Listen for grid events\n useEffect(() => {\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\n const allSubscriptions = new Subscription();\n\n // NOTE: We use observables for various events like page scroll and mouse events,\n // for performance reasons, so only applicable rows re-render as needed\n if (shouldRespondToMouseEvents) {\n // Row mouse enter event\n allSubscriptions.add(\n rowMouseEnter$.subscribe((v) => {\n setIsHovered(v.gridSectionId === gridSectionId && v.rowNumber === rowNumber);\n }),\n );\n\n // Row mouse leave event\n allSubscriptions.add(\n rowMouseLeave$.subscribe((v) => {\n setIsHovered(false);\n }),\n );\n }\n\n // Selected rows change event\n if ((btGridRow as BTGridRowPrimary).isSelectable) {\n allSubscriptions.add(\n selectedRowsChange$.subscribe((selectedItems) => {\n setIsSelected(\n selectedItems.some(\n (v) =>\n v.groupingKey === collapseOrSelectGroupingKey &&\n v.rowId === correspondingPrimaryGridSectionGridRow.id,\n ),\n );\n }),\n );\n }\n\n // Collapsed rows change event\n allSubscriptions.add(\n collapsedRowsChange$.subscribe((collapsedItems) => {\n updateCollapseStateVariable(collapsedItems);\n updateVisibleStateVariable(collapsedItems);\n }),\n );\n\n // Drag status changed\n allSubscriptions.add(\n dragStatusChanged$.subscribe((v) => {\n if (!v) {\n setIsActiveDragAndDropTarget_Bottom(false);\n setIsActiveDragAndDropTarget_Top(false);\n setIsActiveDragAndDropTarget_Left(false);\n setIsActiveDragAndDropTarget_Right(false);\n setIsInvalidDropTarget(false);\n }\n }),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [\n btGridRow,\n collapsedRowsChange$,\n collapseOrSelectGroupingKey,\n correspondingPrimaryGridSectionGridRow,\n gridSectionId,\n isHovered,\n pageScroll_X$,\n pageScroll_Y$,\n rowMouseEnter$,\n rowMouseLeave$,\n rowNumber,\n selectedRowsChange$,\n shouldRespondToMouseEvents,\n updateCollapseStateVariable,\n updateVisibleStateVariable,\n dragStatusChanged$,\n isActiveDragAndDropTarget_Left,\n ]);\n\n const onRowClick_CollapsibleRow = useCallback(\n (event: React.MouseEvent): void => {\n // If a click into an input element on the row triggered the event, ignore it\n if (event.target instanceof HTMLInputElement) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n onRowClick({\n gridSectionId,\n sortableContainerId:\n correspondingPrimaryGridSectionGridRow.sortableInfo?.sortableContainerId ?? null,\n rowId: correspondingPrimaryGridSectionGridRow.id,\n groupingKey: collapseOrSelectGroupingKey,\n rowGroupingInfo: {\n isGroupedRow: correspondingPrimaryGridSectionGridRow.groupingInfo?.isGroupedRow ?? false,\n order: correspondingPrimaryGridSectionGridRow.groupingInfo?.order ?? null,\n groupingLevel: correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingLevel ?? null,\n groupingKey1: correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey1 ?? null,\n groupingKey2: correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey2 ?? null,\n groupingParent1Info:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingParent1Info,\n groupingParent2Info:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingParent2Info,\n globalCollapseResponseKey:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseResponseKey ?? null,\n globalCollapseTriggerKey:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseTriggerKey ?? null,\n },\n });\n },\n [\n onRowClick,\n gridSectionId,\n correspondingPrimaryGridSectionGridRow.sortableInfo?.sortableContainerId,\n correspondingPrimaryGridSectionGridRow.id,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.isGroupedRow,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.order,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingLevel,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey1,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey2,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingParent1Info,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingParent2Info,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseResponseKey,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseTriggerKey,\n collapseOrSelectGroupingKey,\n ],\n );\n\n const onRowClick_SelectableRow = useCallback(\n (event: React.MouseEvent | null): void => {\n if (!isReadOnly && onRowCheckboxClick) {\n // NOTE: We do not want to prevent the default event action, just stop it from bubbling up\n if (event) {\n event.stopPropagation();\n }\n\n onRowCheckboxClick({\n gridSectionId: gridSectionId,\n groupingKey: collapseOrSelectGroupingKey,\n rowGroupingInfo: {\n isGroupedRow:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.isGroupedRow ?? false,\n order: correspondingPrimaryGridSectionGridRow.groupingInfo?.order ?? null,\n groupingLevel:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingLevel ?? null,\n groupingKey1: correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey1 ?? null,\n groupingKey2: correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey2 ?? null,\n groupingParent1Info:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingParent1Info,\n groupingParent2Info:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingParent2Info,\n globalCollapseResponseKey:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseResponseKey ??\n null,\n globalCollapseTriggerKey:\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseTriggerKey ?? null,\n },\n rowId: correspondingPrimaryGridSectionGridRow.id,\n sortableContainerId:\n correspondingPrimaryGridSectionGridRow.sortableInfo?.sortableContainerId ?? null,\n });\n }\n },\n [\n isReadOnly,\n onRowCheckboxClick,\n correspondingPrimaryGridSectionGridRow.sortableInfo,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.isGroupedRow,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.order,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingLevel,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey1,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingKey2,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingParent1Info,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.groupingParent2Info,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseResponseKey,\n correspondingPrimaryGridSectionGridRow.groupingInfo?.globalCollapseTriggerKey,\n correspondingPrimaryGridSectionGridRow.id,\n gridSectionId,\n collapseOrSelectGroupingKey,\n ],\n );\n\n // Since not all rows have the same features, we do not want to re-render certain rows if a prop changed\n // but they don't use it.\n const onRowClickHandler_Collapse = (btGridRow as BTGridRowPrimary).isCollapsibleTrigger\n ? onRowClick_CollapsibleRow\n : mouseEventNoOpHandler;\n\n const onRowClickHandler_Select = (btGridRow as BTGridRowPrimary).isSelectable\n ? onRowClick_SelectableRow\n : mouseEventNoOpHandler;\n\n const onMouseEnterHandler = useCallback((): void => {\n if (shouldRespondToMouseEvents) {\n onRowMouseEnter({ gridSectionId, rowNumber });\n }\n }, [shouldRespondToMouseEvents, onRowMouseEnter, gridSectionId, rowNumber]);\n\n const getDropTargetStatus = useCallback((): DragAndDropDirection[] | null => {\n const returnValue: DragAndDropDirection[] = [];\n\n // Ensure the dragged item and the drop target are in the same sortable container\n if (\n itemBeingDraggedInfo.current &&\n btGridRow.sortableInfo &&\n itemBeingDraggedInfo.current.sortableContainerId ===\n btGridRow.sortableInfo.sortableContainerId\n ) {\n const rowBeingDraggedIsGroupingRow = itemBeingDraggedInfo.current.isGroupedRow;\n const thisRowIsGroupingRow = btGridRow.groupingInfo?.isGroupedRow ?? false;\n const draggedRowGroupingLevel = itemBeingDraggedInfo.current.row.groupingInfo?.groupingLevel;\n const dropTargetGroupingLevel = btGridRow.groupingInfo?.groupingLevel;\n const draggedRowGroupingKey1 = itemBeingDraggedInfo.current.groupingKey1;\n const draggedRowGroupingKey2 = itemBeingDraggedInfo.current.groupingKey2;\n const dropTargetGroupingKey1 = btGridRow.groupingInfo?.groupingKey1;\n const dropTargetGroupingKey2 = btGridRow.groupingInfo?.groupingKey2;\n const isTheLastElementOfGroupingKey1Parent =\n btGridRow.groupingInfo?.groupingParent1Info?.isTheLastElementOfThisParent;\n const isTheLastElementOfGroupingKey2Parent =\n btGridRow.groupingInfo?.groupingParent2Info?.isTheLastElementOfThisParent;\n\n // Horizontal\n if (btGridRow.sortableInfo.sortableDirection === 'horizontal') {\n // If we are dragging a non-group row\n if (!rowBeingDraggedIsGroupingRow) {\n // If we are dropping a non-group row onto a non-group row\n if (!thisRowIsGroupingRow) {\n // If they are in the same group\n if (\n areTrimmedStringsEqual(draggedRowGroupingKey1, dropTargetGroupingKey1) &&\n areTrimmedStringsEqual(draggedRowGroupingKey2, dropTargetGroupingKey2)\n ) {\n returnValue.push('left');\n returnValue.push('right');\n }\n }\n }\n }\n // Vertical\n else {\n // If we are dragging a non-group row\n if (!rowBeingDraggedIsGroupingRow) {\n // If we are dropping a non-group row onto a non-group row\n if (!thisRowIsGroupingRow) {\n // If they are in the same group\n if (\n areTrimmedStringsEqual(draggedRowGroupingKey1, dropTargetGroupingKey1) &&\n areTrimmedStringsEqual(draggedRowGroupingKey2, dropTargetGroupingKey2)\n ) {\n returnValue.push('top');\n returnValue.push('bottom');\n }\n // Dropping a level 0 row after the last element of a level 0 or level 1 group\n else if (draggedRowGroupingLevel === 0 && isTheLastElementOfGroupingKey1Parent) {\n returnValue.push('bottom');\n }\n // Dropping a level 1 row after the last element of a level 1 group\n else if (\n draggedRowGroupingLevel === 1 &&\n dropTargetGroupingLevel === 2 &&\n areTrimmedStringsEqual(draggedRowGroupingKey1, dropTargetGroupingKey1) &&\n isTheLastElementOfGroupingKey2Parent\n ) {\n returnValue.push('bottom');\n }\n }\n // If we are dropping a non-group row onto a group row\n else {\n // If we are dropping a non-group row onto its own group\n if (\n areTrimmedStringsEqual(draggedRowGroupingKey1, dropTargetGroupingKey1) &&\n areTrimmedStringsEqual(draggedRowGroupingKey2, dropTargetGroupingKey2) &&\n !isCollapsed\n ) {\n returnValue.push('bottom');\n }\n // Dropping level 1 non-group row onto a level 1 group row\n else if (\n draggedRowGroupingLevel === 1 &&\n draggedRowGroupingLevel === dropTargetGroupingLevel &&\n areTrimmedStringsEqual(draggedRowGroupingKey1, dropTargetGroupingKey1)\n ) {\n returnValue.push('top');\n if (isCollapsed) {\n returnValue.push('bottom');\n }\n }\n // Dropping level 0 non-group row onto a level 0 group row\n else if (\n draggedRowGroupingLevel === 0 &&\n draggedRowGroupingLevel === dropTargetGroupingLevel\n ) {\n returnValue.push('top');\n if (isCollapsed) {\n returnValue.push('bottom');\n }\n }\n // Dropping a level 0 row after a line 1 collapsed group\n else if (\n draggedRowGroupingLevel === 0 &&\n dropTargetGroupingLevel === 1 &&\n isTheLastElementOfGroupingKey1Parent &&\n isCollapsed\n ) {\n returnValue.push('bottom');\n }\n }\n }\n // If we are dragging a group row\n else {\n // If we are dropping a grouped row onto a grouped row\n if (thisRowIsGroupingRow) {\n // Dropping level 1 grouped row onto level 1 grouped row\n if (\n draggedRowGroupingLevel === 1 &&\n draggedRowGroupingLevel === dropTargetGroupingLevel &&\n areTrimmedStringsEqual(draggedRowGroupingKey1, dropTargetGroupingKey1)\n ) {\n returnValue.push('top');\n if (isCollapsed) {\n returnValue.push('bottom');\n }\n }\n // Dropping level 0 grouped row onto level 0 grouped row\n else if (\n draggedRowGroupingLevel === 0 &&\n draggedRowGroupingLevel === dropTargetGroupingLevel\n ) {\n returnValue.push('top');\n if (isCollapsed) {\n returnValue.push('bottom');\n }\n }\n // Dropping level 1 grouped row onto level 0 grouped row\n else if (\n draggedRowGroupingLevel === 1 &&\n dropTargetGroupingLevel === 0 &&\n areTrimmedStringsEqual(draggedRowGroupingKey1, dropTargetGroupingKey1) &&\n !isCollapsed\n ) {\n returnValue.push('bottom');\n }\n // Dropping level 0 group after the last collapsed child group of another level 1 group\n else if (\n draggedRowGroupingLevel === 0 &&\n dropTargetGroupingLevel === 1 &&\n isTheLastElementOfGroupingKey1Parent &&\n isCollapsed\n ) {\n returnValue.push('bottom');\n }\n }\n // If we are dropping a grouped row onto a non-grouped row\n else {\n // Dropping level 1 grouped row onto a level 1 non-grouped row\n if (\n draggedRowGroupingLevel === 1 &&\n draggedRowGroupingLevel === dropTargetGroupingLevel &&\n areTrimmedStringsEqual(draggedRowGroupingKey1, dropTargetGroupingKey1)\n ) {\n returnValue.push('top');\n returnValue.push('bottom');\n }\n // Dropping level 0 grouped row onto a level 0 non-grouped row\n else if (\n draggedRowGroupingLevel === 0 &&\n draggedRowGroupingLevel === dropTargetGroupingLevel\n ) {\n returnValue.push('top');\n returnValue.push('bottom');\n }\n // Dropping a level 0 group after the last element of another level 0 or level 1 group\n else if (draggedRowGroupingLevel === 0 && isTheLastElementOfGroupingKey1Parent) {\n returnValue.push('bottom');\n }\n // Dropping a level 1 group after the last element of another level 1 group\n else if (\n draggedRowGroupingLevel === 1 &&\n dropTargetGroupingLevel === 2 &&\n areTrimmedStringsEqual(draggedRowGroupingKey1, dropTargetGroupingKey1) &&\n isTheLastElementOfGroupingKey2Parent\n ) {\n returnValue.push('bottom');\n }\n }\n }\n }\n\n return returnValue;\n } else {\n return null;\n }\n }, [btGridRow, isCollapsed, itemBeingDraggedInfo]);\n\n const onMouseLeaveHandler = useCallback((): void => {\n if (shouldRespondToMouseEvents) {\n onRowMouseLeave({ gridSectionId, rowNumber });\n }\n\n if (itemBeingDraggedInfo.current && btGridRow.sortableInfo) {\n const dropTargetStatus = getDropTargetStatus();\n\n // If this row is sortable and is a valid drop target for the row being dragged\n if (dropTargetStatus !== null) {\n // We debounce mouse move events, for performance, so if we have an active timeout pending, cancel it\n if (dragAndDropResponseTimeout.current) {\n clearTimeout(dragAndDropResponseTimeout.current);\n dragAndDropResponseTimeout.current = null;\n }\n\n if (itemBeingDraggedInfo.current?.direction === 'vertical') {\n setIsActiveDragAndDropTarget_Bottom(false);\n setIsActiveDragAndDropTarget_Top(false);\n } else {\n setIsActiveDragAndDropTarget_Left(false);\n setIsActiveDragAndDropTarget_Right(false);\n }\n\n setIsInvalidDropTarget(false);\n }\n }\n }, [\n shouldRespondToMouseEvents,\n btGridRow,\n itemBeingDraggedInfo,\n onRowMouseLeave,\n gridSectionId,\n rowNumber,\n getDropTargetStatus,\n ]);\n\n const onMouseMoveHandler = useCallback(\n (e): void => {\n const dropTargetStatus = getDropTargetStatus();\n\n // If this row is sortable and is a valid drop target for the row being dragged\n if (\n dropTargetStatus !== null &&\n (dropTargetStatus.includes('top') ||\n dropTargetStatus.includes('bottom') ||\n dropTargetStatus.includes('left') ||\n dropTargetStatus.includes('right'))\n ) {\n // Debounce this so it doesn't fire with every single mouse move event\n if (dragAndDropResponseTimeout.current) {\n return;\n }\n\n // NOTE: We assign the event target to a local variable outside of the timeout, because it's a synthetic event\n // that gets reused and the target will not be present inside the setTimeout\n let targetElement = e.target as HTMLElement | null;\n\n dragAndDropResponseTimeout.current = setTimeout(() => {\n if (!targetElement!.matches('.btGridRow')) {\n targetElement = targetElement!.closest('.btGridRow');\n }\n\n if (\n targetElement?.matches('.btGridRow') &&\n itemBeingDraggedInfo.current &&\n lastMouseCoordinates.current\n ) {\n if (itemBeingDraggedInfo.current.direction === 'vertical') {\n // Vertical\n const currRowTopOffset = getElementOffset(targetElement).top;\n const currRowHeight = targetElement.getBoundingClientRect().height;\n\n const rowMidPoint = currRowTopOffset + currRowHeight / 2;\n // Top half\n if (\n lastMouseCoordinates.current.y < rowMidPoint &&\n dropTargetStatus.includes('top')\n ) {\n setIsActiveDragAndDropTarget_Top(true);\n setIsActiveDragAndDropTarget_Bottom(false);\n }\n // Bottom half\n else if (\n lastMouseCoordinates.current.y >= rowMidPoint &&\n dropTargetStatus.includes('bottom')\n ) {\n setIsActiveDragAndDropTarget_Top(false);\n setIsActiveDragAndDropTarget_Bottom(true);\n }\n } else {\n // Horizontal\n const currRowLeftOffset = getElementOffset(targetElement).left;\n const currRowWidth = targetElement.getBoundingClientRect().width;\n\n const rowMidPoint = currRowLeftOffset + currRowWidth / 2;\n\n // Left half\n if (\n lastMouseCoordinates.current.x < rowMidPoint &&\n dropTargetStatus.includes('left')\n ) {\n setIsActiveDragAndDropTarget_Left(true);\n setIsActiveDragAndDropTarget_Right(false);\n }\n // Right half\n else if (\n lastMouseCoordinates.current.x >= rowMidPoint &&\n dropTargetStatus.includes('right')\n ) {\n setIsActiveDragAndDropTarget_Left(false);\n setIsActiveDragAndDropTarget_Right(true);\n }\n }\n }\n\n dragAndDropResponseTimeout.current = null;\n }, 25);\n\n setIsInvalidDropTarget(false);\n } else if (dropTargetStatus !== null && dropTargetStatus.length === 0) {\n setIsInvalidDropTarget(true);\n setIsActiveDragAndDropTarget_Bottom(false);\n setIsActiveDragAndDropTarget_Top(false);\n setIsActiveDragAndDropTarget_Left(false);\n setIsActiveDragAndDropTarget_Right(false);\n } else {\n setIsInvalidDropTarget(false);\n setIsActiveDragAndDropTarget_Bottom(false);\n setIsActiveDragAndDropTarget_Top(false);\n }\n },\n [getDropTargetStatus, itemBeingDraggedInfo, lastMouseCoordinates],\n );\n\n // NOTE: We memoize this entire component and list specific dependencies, because it will otherwise re-render every single\n // time the props object changes, which happens with every single render (we just destructure the props object here\n // but the containing object will change)\n return useMemo(() => {\n const btGridRowAsPrimary = btGridRow as BTGridRowPrimary;\n\n // NOTE: We do nothing here, we just need the rerenderId as a dependency to this useMemo, and if we don't explicitly use it somewhere,\n // it can accidentally get stripped out if we let the linter update the dependency array\n if (rerenderStatus) {\n }\n\n const getRowClass = (): string => {\n const returnValue: string[] = [];\n\n // NOTE: When the rerender ID is set, we want to display this row, overriding any animations / bootstrap collapse CSS styles,\n // so we can get accurate measurements for the row dimensions in the grid container component.\n if (rerenderStatus !== null) {\n returnValue.push('noCollapseAnimation show isRerendering');\n }\n\n if (btGridRow.isHoverable && isHovered) {\n returnValue.push('isHovered');\n }\n\n if (correspondingPrimaryGridSectionGridRow?.isSelectable && isSelected) {\n returnValue.push('isSelected');\n }\n\n if (isActiveDragAndDropTarget_Bottom) {\n returnValue.push('isActiveDragAndDropTarget dropBelowTarget');\n } else if (isActiveDragAndDropTarget_Top) {\n returnValue.push('isActiveDragAndDropTarget dropAboveTarget');\n } else if (isActiveDragAndDropTarget_Left) {\n returnValue.push('isActiveDragAndDropTarget dropLeftTarget');\n } else if (isActiveDragAndDropTarget_Right) {\n returnValue.push('isActiveDragAndDropTarget dropRightTarget');\n } else if (isInvalidDropTarget) {\n returnValue.push('invalidDragAndDropTarget');\n }\n\n if (\n btGridRow.isPrimaryGridRow &&\n correspondingPrimaryGridSectionGridRow?.isCollapsibleTrigger\n ) {\n returnValue.push('pointer isCollapsible');\n }\n\n if (!(typeof btGridRow.showBottomBorder === 'boolean' ? btGridRow.showBottomBorder : true)) {\n returnValue.push('noBorder');\n }\n\n switch (btGridRow.bottomBorderColor) {\n case 'black':\n returnValue.push('blackBorder');\n break;\n\n default:\n break;\n }\n\n return returnValue.join(' ');\n };\n\n const dataAttributes: Record = {};\n\n if (btGridRow.dataAttributes) {\n Object.keys(btGridRow.dataAttributes).forEach((currKey) => {\n dataAttributes[`data-${currKey}`] = btGridRow.dataAttributes![currKey];\n });\n }\n\n let dragStartedTimeout: NodeJS.Timeout | null = null;\n\n let returnValue: JSX.Element = (\n {\n if (btGridRow.sortableInfo) {\n if (dragStartedTimeout) {\n clearTimeout(dragStartedTimeout);\n dragStartedTimeout = null;\n }\n\n // Remove blue line that is used to indicate drop position\n if (btGridRow.sortableInfo.sortableDirection === 'vertical') {\n setIsActiveDragAndDropTarget_Bottom(false);\n setIsActiveDragAndDropTarget_Top(false);\n } else {\n setIsActiveDragAndDropTarget_Left(false);\n setIsActiveDragAndDropTarget_Right(false);\n }\n\n // Trigger observable for reordering\n if (!isInvalidDropTarget && itemBeingDraggedInfo.current) {\n let direction: 'top' | 'bottom' | 'left' | 'right';\n if (isActiveDragAndDropTarget_Top) {\n direction = 'top';\n } else if (isActiveDragAndDropTarget_Bottom) {\n direction = 'bottom';\n } else if (isActiveDragAndDropTarget_Left) {\n direction = 'left';\n } else if (isActiveDragAndDropTarget_Right) {\n direction = 'right';\n } else {\n return;\n }\n\n onItemsReordered({\n dragInfo: itemBeingDraggedInfo.current,\n dropTarget: btGridRow,\n dropDirection: direction,\n });\n }\n }\n\n if (!elementBeingDragged.current) {\n onRowClickHandler_Collapse(e);\n }\n }}\n >\n {btGridRow.sortableInfo && btGridRow.sortableInfo.sortableDirection === 'horizontal' ? (\n // For horizontal drag and drop, we output an absolutely positioned element at the top of the cell\n // for the user to click and drag\n <>\n {\n if (btGridRow.sortableInfo) {\n const targetElement = e.target as HTMLElement;\n\n itemBeingDraggedInfo.current = {\n direction: btGridRow.sortableInfo!.sortableDirection,\n isGroupedRow: btGridRow.groupingInfo?.isGroupedRow ?? false,\n sortableContainerId: btGridRow.sortableInfo!.sortableContainerId,\n groupingKey1: btGridRow.groupingInfo?.groupingKey1 || null,\n groupingKey2: btGridRow.groupingInfo?.groupingKey2 || null,\n row: btGridRow,\n };\n\n elementBeingDragged.current = targetElement.closest('.btGridRow');\n\n onDragStatusChanged(true);\n\n dragStartedTimeout = null;\n }\n }}\n >\n \n \n \n \n \n ) : (\n <>\n )}\n {btGridRow.sortableInfo && btGridRow.sortableInfo.sortableDirection === 'vertical' ? (\n {\n onSetCellRef({ gridSectionId, element: el!, rowNumber });\n }}\n className={`cellColumn cellWidth-${isReadOnly ? 'none' : 'xs'} ${\n isReadOnly ? '' : 'grab'\n } ${easterEgg_BoogieNights ? 'ee' : ''} ${getAdditionalStylesClasses([\n 'border-left',\n ])}`.trim()}\n // NOTE: The parameters around x and y offsets don't apply to these checkbox cells\n style={getCellStyle({\n currCell: null,\n easterEgg_BoogieNights,\n frozenCell_InitialXOffset: 0,\n frozenCell_InitialYOffset: 0,\n isPlaceholderForHorizontalFrozenCell: false,\n isPlaceholderForVerticalFrozenCell: false,\n pageScrollOffset_X: 0,\n pageScrollOffset_Y: 0,\n rowHeight: rowHeight,\n })}\n onPointerDown={(e) => {\n if (btGridRow.sortableInfo) {\n const targetElement = e.target as HTMLElement;\n\n itemBeingDraggedInfo.current = {\n direction: btGridRow.sortableInfo!.sortableDirection,\n isGroupedRow: btGridRow.groupingInfo?.isGroupedRow ?? false,\n sortableContainerId: btGridRow.sortableInfo!.sortableContainerId,\n groupingKey1: btGridRow.groupingInfo?.groupingKey1 || null,\n groupingKey2: btGridRow.groupingInfo?.groupingKey2 || null,\n row: btGridRow,\n };\n\n elementBeingDragged.current = targetElement.closest('.btGridRow');\n\n onDragStatusChanged(true);\n\n dragStartedTimeout = null;\n }\n }}\n title={t('general:clickAndHoldToDrag')}\n >\n
    \n {isReadOnly ? (\n <>\n ) : (\n \n \n \n )}\n
    \n \n ) : (\n <>\n )}\n\n {/* If the row is selectable, we add a cell with a checkbox */}\n {(btGridRow as BTGridRowPrimary).isSelectable ? (\n {\n onSetCellRef({ gridSectionId, element: el!, rowNumber });\n }}\n className={`cellColumn cellWidth-${isReadOnly ? 'none' : 'xs'} ${\n isReadOnly ? '' : 'pointer'\n } ${easterEgg_BoogieNights ? 'ee' : ''} ${getAdditionalStylesClasses(\n (btGridRow as BTGridRowPrimary).selectableCellAdditionalStyles,\n )}`.trim()}\n // NOTE: The parameters around x and y offsets don't apply to these checkbox cells\n style={getCellStyle({\n currCell: null,\n easterEgg_BoogieNights,\n frozenCell_InitialXOffset: 0,\n frozenCell_InitialYOffset: 0,\n isPlaceholderForHorizontalFrozenCell: false,\n isPlaceholderForVerticalFrozenCell: false,\n pageScrollOffset_X: 0,\n pageScrollOffset_Y: 0,\n rowHeight: rowHeight,\n })}\n // NOTE: We put the onPointerUp handler for the checkbox on the cell itself, for easier selection by the user\n onPointerUp={(e) => {\n // NOTE: Do not process the event if an row is being dragged\n if (!elementBeingDragged.current) {\n onRowClickHandler_Select(e);\n }\n }}\n >\n
    \n {isReadOnly ? (\n <>\n ) : (\n <>\n {correspondingPrimaryGridSectionGridRow.groupingInfo?.isGroupedRow ?? false ? (\n \n \n \n ) : (\n \n )}\n \n )}\n
    \n \n ) : (\n <>\n )}\n\n {btGridRow.cells.flatMap((currCell, i) => {\n // NOTE: When we have frozen cells, we do some black magic and output the cell twice.\n // One will fill space as usual and the other will be absolutely positioned and hidden in the same spot.\n // When the user scrolls, the second cell will show and animate and the original cell will remain as is.\n // This is done because many cells in the grid contain borders or other \"structural\" styles\n // that can be affected by the CSS of floating cells if we mutate the original cell's style, and having a \"ghost\"\n // cell floating looks visually better than cells actually moving.\n const returnValue2: JSX.Element[] = [\n ,\n ];\n\n if (currCell.frozenOnHorizontalScroll) {\n // NOTE: We update frozen horizontal cells to be 'xl', so they should be equal across different grid sections\n const cellCopy = { ...currCell };\n cellCopy.cellWidth = 'xl';\n\n returnValue2.push(\n ,\n );\n } else if (currCell.frozenOnVerticalScroll) {\n returnValue2.push(\n ,\n );\n }\n\n return returnValue2;\n })}\n \n );\n\n if (\n btGridRow.isPrimaryGridRow &&\n (btGridRowAsPrimary.isSelectable ||\n (btGridRow as BTGridRowPrimary).contextMenuItems ||\n (btGridRow as BTGridRowPrimary).contextMenuItemsJSX)\n ) {\n let contextMenuItems = (btGridRow as BTGridRowPrimary).contextMenuItems ?? [];\n const contextMenuItemsJSX = (btGridRow as BTGridRowPrimary).contextMenuItemsJSX;\n\n // If we already have a context menu and the row can be selected, add in a 'select' / 'deselect' option\n if (btGridRowAsPrimary.isSelectable) {\n const isGroupedRow =\n correspondingPrimaryGridSectionGridRow.groupingInfo?.isGroupedRow ?? false;\n let selectMenuItemText = '';\n\n if (isGroupedRow) {\n selectMenuItemText = t('general:toggleItemsInThisGroup');\n } else {\n selectMenuItemText = isSelected ? t('general:deselect') : t('general:select');\n }\n\n contextMenuItems = [\n {\n id: 'Select',\n icon: 'check',\n text: selectMenuItemText,\n onClick: () => {\n onRowClick_SelectableRow(null);\n },\n },\n {\n id: 'SelectButtonDivider',\n isDivider: true,\n },\n ...contextMenuItems,\n ];\n }\n\n returnValue = (\n \n {returnValue}\n \n );\n }\n\n return returnValue;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n rerenderStatus,\n testId,\n rowNumber,\n isCollapsed,\n isVisible,\n className,\n onRowClickHandler_Collapse,\n isReadOnly,\n easterEgg_BoogieNights,\n onRowClickHandler_Select,\n isSelected,\n isHovered,\n isActiveDragAndDropTarget_Bottom,\n isActiveDragAndDropTarget_Top,\n isActiveDragAndDropTarget_Left,\n isActiveDragAndDropTarget_Right,\n isInvalidDropTarget,\n rowHeight,\n shouldRespondToMouseEvents,\n onRowMouseEnter,\n gridSectionId,\n onRowMouseLeave,\n onSetCellRef,\n\n // NOTE: When grid sections are regenerated, they generate new row objects, which will cause this useMemo\n // to re-run if we have a dependency on the row object itself (btGridRow). This causes a lot of unnecessary re-renders,\n // so by switching it to use JSON.stringify, we can only re-render things when what we are rendering actually changed.\n // NOTE: This could potentially miss function reference changes, but that should not be an issue as we use observables\n // for communication between things in the grid and the pages that use it (bid package / bid summary pages).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(btGridRow),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(correspondingPrimaryGridSectionGridRow),\n ]);\n};\n\nconst mouseEventNoOpHandler = (event: React.MouseEvent) => {\n // NOTE: We do nothing here\n};\n\nexport default BTGridRow;\n","import React, { useMemo } from 'react';\r\nimport BTGridRow from '../grid-row/BTGridRow';\r\n\r\ninterface Props {\r\n gridSectionId: string;\r\n collapseOrSelectGroupingKey: string;\r\n subGrid: BTSubGrid;\r\n // The primary subgrid that will be displayed in the same section as this.\r\n // NOTE: This will be undefined if this subgrid is a primary subgrid.\r\n primarySubGrid: BTSubGrid | undefined;\r\n isReadOnly: boolean;\r\n}\r\n\r\nconst BTSubGrid: React.FC = ({\r\n gridSectionId,\r\n collapseOrSelectGroupingKey,\r\n subGrid,\r\n primarySubGrid,\r\n isReadOnly,\r\n}: Props) => {\r\n return useMemo(() => {\r\n return (\r\n
    \r\n {(subGrid?.auxiliaryRows?.length || 0) > 0 ? (\r\n <>\r\n {subGrid?.auxiliaryRows?.map((currGridSectionRow, i2) => {\r\n // NOTE: We only pass certain event handlers to auxiliary rows\r\n\r\n return (\r\n \r\n );\r\n })}\r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {subGrid?.rows.map((currGridSectionRow, i2) => {\r\n const currRowNumber = i2 + (subGrid?.auxiliaryRows?.length || 0);\r\n\r\n return (\r\n \r\n );\r\n })}\r\n
    \r\n );\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [\r\n gridSectionId,\r\n isReadOnly,\r\n\r\n // NOTE: When grid sections are regenerated, they generate new row objects, which will cause this useMemo\r\n // to re-run if we have a dependency on the row object itself (btGridRow). This causes a lot of unnecessary re-renders,\r\n // so by switching it to use JSON.stringify, we can only re-render things when what we are rendering actually changed.\r\n // NOTE: This could potentially miss function reference changes, but that should not be an issue as we use observables\r\n // for communication between things in the grid and the pages that use it (bid package / bid summary pages).\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n JSON.stringify(primarySubGrid),\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n JSON.stringify(subGrid),\r\n subGrid.testId,\r\n ]);\r\n};\r\n\r\nexport default BTSubGrid;\r\n","import React, { useMemo } from 'react';\r\nimport BTSubGrid from '../sub-grid/BTSubGrid';\r\n\r\ninterface Props {\r\n isReadOnly: boolean;\r\n addTopMargin: boolean;\r\n testId: string;\r\n gridSectionZIndexBase: number;\r\n getPrimaryGridStyle: () => Dictionary;\r\n setPrimaryGridRef: (element: HTMLElement | null) => void;\r\n gridSection: BTGridSection;\r\n}\r\n\r\nconst BTGridContainerGridSection: React.FC = ({\r\n isReadOnly,\r\n addTopMargin,\r\n testId,\r\n gridSectionZIndexBase,\r\n getPrimaryGridStyle,\r\n setPrimaryGridRef,\r\n gridSection,\r\n}) => {\r\n return useMemo(() => {\r\n return (\r\n \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n\r\n {gridSection.secondaryGrids.map((currSecondaryGrid, i2) => {\r\n // Decrease the z-index by 1 as we display secondary grids from left to right for the current\r\n // grid section\r\n const currSecondaryGridZIndex = gridSectionZIndexBase - (i2 + 2);\r\n\r\n return (\r\n \r\n
    \r\n \r\n
    \r\n \r\n );\r\n })}\r\n \r\n \r\n );\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [\r\n addTopMargin,\r\n getPrimaryGridStyle,\r\n gridSection.id,\r\n // NOTE: When grid sections are regenerated, they generate new objects, which will cause this useMemo\r\n // to re-run if we have a dependency on the object itself. This causes a lot of unnecessary re-renders,\r\n // so by switching it to use JSON.stringify, we can only re-render things when what we are rendering actually changed.\r\n // NOTE: This could potentially miss function reference changes, but that should not be an issue as we use observables\r\n // for communication between things in the grid and the pages that use it (bid package / bid summary pages).\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n JSON.stringify(gridSection.primaryGrid),\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n JSON.stringify(gridSection.secondaryGrids),\r\n gridSectionZIndexBase,\r\n isReadOnly,\r\n setPrimaryGridRef,\r\n testId,\r\n ]);\r\n};\r\n\r\nexport default BTGridContainerGridSection;\r\n","import { isEqual, sortBy, uniq } from 'lodash';\r\nimport { useCallback, useContext, useEffect, useRef } from 'react';\r\nimport GeneralConstants from '../../../../../constants/general';\r\nimport { getElementOffset } from '../../../../../utils/dom';\r\nimport { BTGeneralContext } from '../../../general-contexts/BTGeneralContext';\r\n\r\ninterface ReturnValue {\r\n onKeyDown: (e: React.KeyboardEvent) => void;\r\n}\r\n\r\ninterface Props {\r\n gridRowReferenceCollections: Array;\r\n}\r\n\r\nconst useBTGridContainerKeyboardNavigation = ({\r\n gridRowReferenceCollections,\r\n}: Props): ReturnValue => {\r\n const { setEasterEgg_BoogieNights } = useContext(BTGeneralContext);\r\n\r\n // Used for the EE, only in development\r\n const currentKeyboardEntry = useRef([]);\r\n\r\n useEffect(() => {\r\n if (isEqual(currentKeyboardEntry, eeKeyboardSequence)) {\r\n // Let's party\r\n setEasterEgg_BoogieNights(true);\r\n\r\n // This party.... is oooooover!\r\n setTimeout(() => {\r\n setEasterEgg_BoogieNights(false);\r\n }, 8000);\r\n\r\n currentKeyboardEntry.current = [];\r\n }\r\n }, [currentKeyboardEntry, setEasterEgg_BoogieNights]);\r\n\r\n const onKeyDown = useCallback(\r\n (e: React.KeyboardEvent) => {\r\n // Persist the event so it doesn't get reused by React\r\n e.persist();\r\n\r\n // EE logic\r\n if (eeKeyboardSequence.includes(e.key.toLowerCase())) {\r\n const currValue = currentKeyboardEntry.current;\r\n const lengthOfKeyboardEntry = currValue.length;\r\n const key2 = e.key.toLowerCase();\r\n let copy = [...currValue];\r\n\r\n if (eeKeyboardSequence[lengthOfKeyboardEntry] === key2) {\r\n copy.push(key2);\r\n } else {\r\n copy = [];\r\n }\r\n\r\n currentKeyboardEntry.current = copy;\r\n } else {\r\n currentKeyboardEntry.current = [];\r\n }\r\n\r\n // NOTE: We no longer capture the left / right arrow keys for navigation, but instead rely on capturing tab and shift / tab.\r\n // This change allows the user to navigate between text inside an input with the left / right arrow keys.\r\n const allowedKeys = [\r\n GeneralConstants.KEY_ARROW_UP,\r\n GeneralConstants.KEY_ARROW_DOWN,\r\n GeneralConstants.KEY_ENTER,\r\n GeneralConstants.KEY_TAB,\r\n ];\r\n if (!allowedKeys.includes(e.key)) {\r\n return;\r\n }\r\n\r\n // We only care about tab on select elements\r\n if (\r\n (e.target as HTMLElement).matches('select') &&\r\n ![GeneralConstants.KEY_TAB].includes(e.key)\r\n ) {\r\n return;\r\n }\r\n\r\n type InputElementObj = {\r\n element: HTMLInputElement;\r\n row: number;\r\n leftOffset: number;\r\n topOffset: number;\r\n };\r\n\r\n const allInputElements: InputElementObj[] = [];\r\n\r\n const allGridRowReferences = gridRowReferenceCollections.flatMap((v) => v.gridRowReferences);\r\n\r\n // Get references to the input elements in the grid container\r\n allGridRowReferences.forEach((currGridRowReference, i) => {\r\n currGridRowReference.gridCellReferences.forEach((currGridCellReference) => {\r\n const inputElements = currGridCellReference.element?.querySelectorAll(\r\n 'input:not(:disabled), select:not(:disabled)',\r\n );\r\n\r\n inputElements?.forEach((currInputElement) => {\r\n const currInputElementAsHtmlElement = currInputElement as HTMLInputElement;\r\n const offset = getElementOffset(currInputElementAsHtmlElement);\r\n\r\n allInputElements.push({\r\n element: currInputElementAsHtmlElement,\r\n row: i,\r\n leftOffset: offset.left,\r\n topOffset: offset.top,\r\n });\r\n });\r\n });\r\n });\r\n\r\n switch (e.key) {\r\n // Note: Left/Right arrow navigation has been disabled for BTGrids to allow cell Left/Right cursor navigation -\r\n // \"Tab\" and \"Shift + Tab\" serve as Left and Right Navigation respectively\r\n case GeneralConstants.KEY_TAB:\r\n {\r\n const matchingInputElement = allInputElements.find((v) => v.element === e.target);\r\n if (matchingInputElement) {\r\n let allInputsOnRow = allInputElements.filter(\r\n (v) => v.row === matchingInputElement.row,\r\n );\r\n if (allInputsOnRow.length) {\r\n allInputsOnRow = sortBy(allInputsOnRow, (v) => v.leftOffset);\r\n\r\n const indexOfTargetElement = allInputsOnRow.findIndex(\r\n (v) => v.element === e.target,\r\n );\r\n\r\n if (indexOfTargetElement > -1) {\r\n let elementToFocus: HTMLInputElement | null = null;\r\n\r\n const shouldMoveLeft = e.key === GeneralConstants.KEY_TAB && e.shiftKey;\r\n\r\n const shouldMoveRight = e.key === GeneralConstants.KEY_TAB && !e.shiftKey;\r\n\r\n if (shouldMoveLeft) {\r\n elementToFocus = allInputsOnRow[indexOfTargetElement - 1]?.element;\r\n } else if (shouldMoveRight) {\r\n elementToFocus = allInputsOnRow[indexOfTargetElement + 1]?.element;\r\n }\r\n\r\n if (!elementToFocus) {\r\n const orderedRowNumbers = sortBy(\r\n uniq(allInputElements.map((m) => m.row)),\r\n (v) => v,\r\n );\r\n\r\n // If we didn't find an element to the left to focus on, try to find the rightmost element on the previous row\r\n if (shouldMoveLeft) {\r\n const indexOfMatchingElementsRow = orderedRowNumbers.findIndex(\r\n (m) => m === matchingInputElement.row,\r\n );\r\n const sortedElementsOnNextRow = sortBy(\r\n allInputElements.filter(\r\n (m) => m.row === orderedRowNumbers[indexOfMatchingElementsRow - 1],\r\n ),\r\n (m) => m.leftOffset,\r\n );\r\n\r\n const lastItemOfPrevRow =\r\n sortedElementsOnNextRow[sortedElementsOnNextRow.length - 1];\r\n\r\n if (lastItemOfPrevRow) {\r\n elementToFocus = lastItemOfPrevRow.element;\r\n } else {\r\n // If we didn't find another element to jump to, blur the current element\r\n matchingInputElement.element.blur();\r\n }\r\n }\r\n\r\n // If we didn't find an element to the right to focus on, try to find the leftmost element on the next row\r\n if (shouldMoveRight) {\r\n const indexOfMatchingElementsRow = orderedRowNumbers.findIndex(\r\n (m) => m === matchingInputElement.row,\r\n );\r\n const sortedElementsOnNextRow = sortBy(\r\n allInputElements.filter(\r\n (m) => m.row === orderedRowNumbers[indexOfMatchingElementsRow + 1],\r\n ),\r\n (m) => m.leftOffset,\r\n );\r\n\r\n const firstItemOfNextRow = sortedElementsOnNextRow[0];\r\n\r\n if (firstItemOfNextRow) {\r\n elementToFocus = firstItemOfNextRow.element;\r\n } else {\r\n // If we didn't find another element to jump to, blur the current element\r\n matchingInputElement.element.blur();\r\n }\r\n }\r\n }\r\n\r\n if (elementToFocus) {\r\n elementToFocus.focus();\r\n if (elementToFocus.select) {\r\n elementToFocus.select();\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n break;\r\n\r\n case GeneralConstants.KEY_ARROW_UP:\r\n case GeneralConstants.KEY_ARROW_DOWN:\r\n case GeneralConstants.KEY_ENTER:\r\n {\r\n const matchingInputElement = allInputElements.find((v) => v.element === e.target);\r\n if (matchingInputElement) {\r\n // Since different rows can have different cell sizes, we can't rely on cell index info when determining which element to jump to.\r\n // What we do instead is get the center coordinates of the current input element and find any other input elements whose dimensions overlap it,\r\n // plus a margin of error.\r\n const centerOffsetOfTargetElement =\r\n matchingInputElement.leftOffset + matchingInputElement.element.offsetWidth / 2;\r\n\r\n const elementsThatIntersectTargetElementCenter_GiveOrTake50Feet = sortBy(\r\n allInputElements.filter(\r\n (v) =>\r\n centerOffsetOfTargetElement >= v.leftOffset - 50 &&\r\n centerOffsetOfTargetElement <= v.leftOffset + v.element.offsetWidth + 50,\r\n ),\r\n (v) => v.topOffset,\r\n );\r\n\r\n const indexOfTargetElement = elementsThatIntersectTargetElementCenter_GiveOrTake50Feet.findIndex(\r\n (v) => v.element === matchingInputElement.element,\r\n );\r\n\r\n let elementToFocus: HTMLInputElement | null = null;\r\n\r\n if (e.key === GeneralConstants.KEY_ARROW_UP) {\r\n elementToFocus =\r\n elementsThatIntersectTargetElementCenter_GiveOrTake50Feet[\r\n indexOfTargetElement - 1\r\n ]?.element;\r\n } else if (\r\n [GeneralConstants.KEY_ARROW_DOWN, GeneralConstants.KEY_ENTER].includes(e.key)\r\n ) {\r\n elementToFocus =\r\n elementsThatIntersectTargetElementCenter_GiveOrTake50Feet[\r\n indexOfTargetElement + 1\r\n ]?.element;\r\n }\r\n\r\n if (elementToFocus) {\r\n elementToFocus.focus();\r\n if (elementToFocus.select) {\r\n elementToFocus.select();\r\n }\r\n } else {\r\n // If we didn't find another element to jump to, blur the current element\r\n matchingInputElement.element.blur();\r\n }\r\n }\r\n }\r\n break;\r\n }\r\n\r\n // Stop the event from bubbling up\r\n e.preventDefault();\r\n e.stopPropagation();\r\n },\r\n [gridRowReferenceCollections],\r\n );\r\n\r\n return { onKeyDown };\r\n};\r\n\r\nconst eeKeyboardSequence = [\r\n GeneralConstants.KEY_ARROW_UP,\r\n GeneralConstants.KEY_ARROW_UP,\r\n GeneralConstants.KEY_ARROW_DOWN,\r\n GeneralConstants.KEY_ARROW_DOWN,\r\n GeneralConstants.KEY_ARROW_LEFT,\r\n GeneralConstants.KEY_ARROW_RIGHT,\r\n GeneralConstants.KEY_ARROW_LEFT,\r\n GeneralConstants.KEY_ARROW_RIGHT,\r\n GeneralConstants.KEY_B,\r\n GeneralConstants.KEY_A,\r\n GeneralConstants.KEY_ENTER,\r\n].map((v) => v.toLowerCase());\r\n\r\nexport default useBTGridContainerKeyboardNavigation;\r\n","import React, {\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useLayoutEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from 'react';\r\nimport { Subscription } from 'rxjs';\r\nimport GeneralConstants from '../../../../constants/general';\r\nimport { useLogger } from '../../../../services/logger/Logger';\r\nimport { normalizeNullOrUndefined } from '../../../../utils/general';\r\nimport { generateUuid } from '../../../../utils/uuid';\r\nimport BTGridDraggedElement from '../BTGridDraggedElement';\r\nimport './BTGridContainer.scss';\r\nimport { BTGridContainerContext, BTGridRerenderStatus } from './BTGridContainerContext';\r\nimport BTGridContainerGridSection from './BTGridContainerGridSection';\r\nimport useBTGridContainerKeyboardNavigation from './hooks/useBTGridContainerKeyboardNavigation';\r\n\r\nexport type GridRerenderTrigger = {\r\n rowsChanged?: boolean;\r\n primaryGridColumnsChanged?: boolean;\r\n};\r\n\r\ninterface Props {\r\n gridRerenderTriggerObject: GridRerenderTrigger;\r\n gridSections: BTGridSection[];\r\n isReadOnly: boolean;\r\n // Lets us specify the primary grid's z-index. This is useful for when we have frozen cells,\r\n // and we want to specify whether they should stay on top of or go behind content of secondary grids.\r\n primaryGridZIndex?: number;\r\n isFullWidth?: boolean;\r\n}\r\n\r\nconst BTGridContainerInnerComponent: React.FC = ({\r\n gridSections,\r\n gridRerenderTriggerObject,\r\n isReadOnly,\r\n primaryGridZIndex,\r\n isFullWidth,\r\n}) => {\r\n const logger = useLogger();\r\n\r\n const {\r\n // Observables\r\n collapsedRowsChange$,\r\n rowCheckboxClick$,\r\n rowClick$,\r\n rowMouseEnter$,\r\n rowMouseLeave$,\r\n selectedRowsChange$,\r\n setCellRef$,\r\n dragStatusChanged$,\r\n\r\n // State variables\r\n rerenderStatus,\r\n\r\n // Ref variables,\r\n rowHeightCollections,\r\n\r\n // Setter methods\r\n onCollapsedRowsChange,\r\n onSelectedRowsChange,\r\n setRerenderStatus,\r\n } = useContext(BTGridContainerContext);\r\n\r\n const gridRowReferenceCollections = useRef>([]);\r\n\r\n const primaryGridReferences = useRef>([]);\r\n\r\n // A copy of the selected rows\r\n const selectedRowsCopy = useRef>([]);\r\n\r\n const { onKeyDown } = useBTGridContainerKeyboardNavigation({\r\n gridRowReferenceCollections: gridRowReferenceCollections.current,\r\n });\r\n\r\n const [isDraggingItem, setIsDraggingItem] = useState(false);\r\n\r\n const [primaryGridsWidth, setPrimaryGridsWidth] = useState();\r\n\r\n const collapsedRowsCopy = useRef([]);\r\n\r\n const gridIsInitialized = useRef(false);\r\n\r\n const previousGridRerenderTriggerObject = useRef();\r\n\r\n const previousRerenderStatus = useRef(null);\r\n\r\n const setCellRef = useCallback(\r\n (gridSectionId: string, element: HTMLElement | null, rowNumber: number): void => {\r\n // There is a super fun react \"feature\" where the ref callback get called twice per render, except for the first render,\r\n // and the first of the two times it passes null as the element parameter.\r\n // https://github.com/facebook/react/issues/9328\r\n if (!element) {\r\n return;\r\n }\r\n\r\n let matchingGridRowReferenceCollection = gridRowReferenceCollections.current.find(\r\n (v) => v.gridSectionId === gridSectionId,\r\n );\r\n\r\n // NOTE: A row reference is for a grid section, and may span primary and secondary subgrids\r\n if (!matchingGridRowReferenceCollection) {\r\n matchingGridRowReferenceCollection = {\r\n gridSectionId: gridSectionId,\r\n gridRowReferences: [],\r\n };\r\n\r\n gridRowReferenceCollections.current.push(matchingGridRowReferenceCollection);\r\n }\r\n\r\n // Add a new row references if we need to\r\n if (matchingGridRowReferenceCollection.gridRowReferences.length - 1 < rowNumber) {\r\n matchingGridRowReferenceCollection.gridRowReferences.push({\r\n gridCellReferences: [],\r\n });\r\n }\r\n\r\n // If the cell reference for this cell wasn't found, add it\r\n const indexOfExistingCellReference = matchingGridRowReferenceCollection.gridRowReferences[\r\n rowNumber\r\n ].gridCellReferences.findIndex((v) => v.element === element);\r\n\r\n if (indexOfExistingCellReference === -1) {\r\n matchingGridRowReferenceCollection.gridRowReferences[rowNumber].gridCellReferences.push({\r\n element: element,\r\n });\r\n } else {\r\n // Replace the cell with the most up-to-date element reference\r\n matchingGridRowReferenceCollection.gridRowReferences[rowNumber].gridCellReferences[\r\n indexOfExistingCellReference\r\n ].element = element;\r\n }\r\n },\r\n [],\r\n );\r\n\r\n const resetCalculatedDimensions_PrimaryGridWidths = useCallback((): void => {\r\n // Reset the calculated dimensions to 'auto'\r\n setPrimaryGridsWidth('auto');\r\n }, []);\r\n\r\n const resetCalculatedDimensions_RowHeights = useCallback((): void => {\r\n // Reset the calculated dimensions to 'auto'\r\n rowHeightCollections.current = [\r\n ...rowHeightCollections.current.map(\r\n (currRowHeightCollection): BTGridRowHeightCollection => {\r\n return {\r\n gridSectionId: currRowHeightCollection.gridSectionId,\r\n rowHeights: currRowHeightCollection.rowHeights.map((v) => 'auto'),\r\n };\r\n },\r\n ),\r\n ];\r\n }, [rowHeightCollections]);\r\n\r\n const recalculateDimensions_PrimaryGridWidths = useCallback((): void => {\r\n // Get and set the max width of the primary grids\r\n const allPrimaryGridWidths = primaryGridReferences.current.map((v) => {\r\n return v.element?.offsetWidth || 0;\r\n });\r\n\r\n if (allPrimaryGridWidths.length) {\r\n setPrimaryGridsWidth(Math.max(...allPrimaryGridWidths));\r\n }\r\n }, []);\r\n\r\n const recalculateDimensions_RowHeights = useCallback((): void => {\r\n const newRowHeightsCollection: BTGridRowHeightCollection[] = gridRowReferenceCollections.current.map(\r\n (currGridRowReferenceCollection) => {\r\n const newRowHeightCollection: BTGridRowHeightCollection = {\r\n gridSectionId: currGridRowReferenceCollection.gridSectionId,\r\n rowHeights: [],\r\n };\r\n\r\n currGridRowReferenceCollection.gridRowReferences.forEach((v) => {\r\n if (!v.gridCellReferences.length) {\r\n newRowHeightCollection.rowHeights.push('auto');\r\n return;\r\n }\r\n\r\n // NOTE: We set a min-height here\r\n newRowHeightCollection.rowHeights.push(\r\n Math.max(\r\n ...v.gridCellReferences.map((v2) => {\r\n return Math.max(v2.element?.offsetHeight || 0, 50);\r\n }),\r\n ),\r\n );\r\n });\r\n\r\n return newRowHeightCollection;\r\n },\r\n );\r\n\r\n rowHeightCollections.current = newRowHeightsCollection;\r\n }, [rowHeightCollections]);\r\n\r\n const onRowCheckboxClick = useCallback(\r\n (newVal: GridSectionRowMetadataMapping): void => {\r\n const existingItemIndex = selectedRowsCopy.current.findIndex(\r\n (v) => v.groupingKey === newVal.groupingKey && v.rowId === newVal.rowId,\r\n );\r\n\r\n let copy = [...selectedRowsCopy.current];\r\n\r\n // When we select a grouped row, Find other rows in this grid section that are children of this row that we may need to select or deselect\r\n if (newVal.rowGroupingInfo.isGroupedRow) {\r\n let childRows: BTGridRowBase[] = [];\r\n\r\n gridSections.forEach((currGridSection) => {\r\n // If the row we just clicked is a root level element, we want to get children that match the first grouping key,\r\n // including other grouped rows\r\n if (normalizeNullOrUndefined(newVal.rowGroupingInfo.groupingKey2) === null) {\r\n const rowsToAdd =\r\n currGridSection?.primaryGrid.rows.filter(\r\n (v) =>\r\n v.id !== newVal.rowId &&\r\n normalizeNullOrUndefined(v.groupingInfo?.groupingKey1) ===\r\n normalizeNullOrUndefined(newVal.rowGroupingInfo.groupingKey1) &&\r\n normalizeNullOrUndefined(v.sortableInfo?.sortableContainerId) ===\r\n normalizeNullOrUndefined(newVal.sortableContainerId),\r\n ) || [];\r\n childRows = childRows.concat(rowsToAdd);\r\n } else {\r\n const rowsToAdd =\r\n currGridSection?.primaryGrid.rows.filter(\r\n (v) =>\r\n v.id !== newVal.rowId &&\r\n !(v.groupingInfo?.isGroupedRow ?? false) &&\r\n normalizeNullOrUndefined(v.groupingInfo?.groupingKey1) ===\r\n normalizeNullOrUndefined(newVal.rowGroupingInfo.groupingKey1) &&\r\n normalizeNullOrUndefined(v.groupingInfo?.groupingKey2) ===\r\n normalizeNullOrUndefined(newVal.rowGroupingInfo.groupingKey2) &&\r\n normalizeNullOrUndefined(v.sortableInfo?.sortableContainerId) ===\r\n normalizeNullOrUndefined(newVal.sortableContainerId),\r\n ) || [];\r\n childRows = childRows.concat(rowsToAdd);\r\n }\r\n });\r\n\r\n const hasUnselectedNonGroupChild = childRows?.some(\r\n (v) =>\r\n !v.groupingInfo?.isGroupedRow &&\r\n copy.findIndex((m) => m.groupingKey === newVal.groupingKey && m.rowId === v.id) === -1,\r\n );\r\n\r\n // If we are selecting a grouped row, if not all of the children are selected, select them all\r\n if (hasUnselectedNonGroupChild) {\r\n if (existingItemIndex === -1) {\r\n copy.push(newVal);\r\n }\r\n\r\n const elementsToAdd: GridSectionRowMetadataMapping[] = childRows.map(\r\n (currChildRow): GridSectionRowMetadataMapping => {\r\n return {\r\n gridSectionId: newVal.gridSectionId,\r\n groupingKey: newVal.groupingKey,\r\n sortableContainerId: newVal.sortableContainerId,\r\n rowId: currChildRow.id,\r\n rowGroupingInfo: {\r\n isGroupedRow: currChildRow.groupingInfo?.isGroupedRow ?? false,\r\n order: currChildRow.groupingInfo?.order ?? null,\r\n groupingLevel: currChildRow.groupingInfo?.groupingLevel ?? null,\r\n groupingKey1: currChildRow.groupingInfo?.groupingKey1 ?? null,\r\n groupingKey2: currChildRow.groupingInfo?.groupingKey2 ?? null,\r\n groupingParent1Info: currChildRow.groupingInfo?.groupingParent1Info,\r\n groupingParent2Info: currChildRow.groupingInfo?.groupingParent2Info,\r\n globalCollapseResponseKey:\r\n currChildRow.groupingInfo?.globalCollapseResponseKey ?? null,\r\n globalCollapseTriggerKey:\r\n currChildRow.groupingInfo?.globalCollapseTriggerKey ?? null,\r\n },\r\n };\r\n },\r\n );\r\n\r\n copy.push(...elementsToAdd);\r\n }\r\n // If we are deselecting a grouped row, regardless of the selected state of the children,\r\n // we want to uncheck them all\r\n else {\r\n if (existingItemIndex > -1) {\r\n copy.splice(existingItemIndex, 1);\r\n }\r\n\r\n const allChildRowIds = childRows.map((v) => v.id);\r\n copy = copy.filter((v) => !allChildRowIds.includes(v.rowId!));\r\n }\r\n }\r\n // If we are select/unselect a row that is not a group row\r\n else {\r\n const isSelectingRow = existingItemIndex === -1;\r\n\r\n if (isSelectingRow) {\r\n copy.push(newVal);\r\n } else {\r\n copy.splice(existingItemIndex, 1);\r\n }\r\n }\r\n\r\n onSelectedRowsChange(copy);\r\n },\r\n [gridSections, onSelectedRowsChange],\r\n );\r\n\r\n // When the grid sections change, we want to go through each grid section and make sure we have an entry in the collapsed\r\n // items array. If we don't, it means the grid section was new and in that case, we want to set the collapsed items from the rows\r\n // in the grid section that are set as default collapsed items.\r\n const initializeCollapsedStates = useCallback(() => {\r\n const copy = [...collapsedRowsCopy.current];\r\n\r\n gridSections.forEach((currGridSection) => {\r\n const groupingKeyToFind = currGridSection.collapseOrSelectGroupingKey ?? currGridSection.id;\r\n\r\n const gridSectionEntry = copy.find((v) => v.groupingKey === groupingKeyToFind);\r\n\r\n if (!gridSectionEntry) {\r\n // If we do not have an entry for this grid section, find out which rows should be collapsed by default\r\n const defaultItemsToCollapse = currGridSection.primaryGrid.rows.filter(\r\n (v) => (v as BTGridRowPrimary).isCollapsedByDefault ?? false,\r\n );\r\n\r\n copy.push({\r\n groupingKey: groupingKeyToFind,\r\n rowMetadataMappings: defaultItemsToCollapse.map(\r\n (v): GridSectionRowMetadataMapping => {\r\n return {\r\n gridSectionId: currGridSection.id,\r\n groupingKey: groupingKeyToFind,\r\n sortableContainerId: v.sortableInfo?.sortableContainerId ?? null,\r\n rowId: null,\r\n rowGroupingInfo: {\r\n isGroupedRow: v.groupingInfo?.isGroupedRow ?? false,\r\n order: v.groupingInfo?.order ?? null,\r\n groupingLevel: v.groupingInfo?.groupingLevel ?? null,\r\n groupingKey1: v.groupingInfo?.groupingKey1 ?? null,\r\n groupingKey2: v.groupingInfo?.groupingKey2 ?? null,\r\n groupingParent1Info: v.groupingInfo?.groupingParent1Info,\r\n groupingParent2Info: v.groupingInfo?.groupingParent2Info,\r\n globalCollapseResponseKey: v.groupingInfo?.globalCollapseResponseKey ?? null,\r\n globalCollapseTriggerKey: v.groupingInfo?.globalCollapseTriggerKey ?? null,\r\n },\r\n };\r\n },\r\n ),\r\n });\r\n } else {\r\n // Remove any mappings for the current grid section that no longer have corresponding rows.\r\n // NOTE: Auxiliary rows don't matter here since they don't have certain functionality, like the ability to collapse.\r\n const allRowsInCurrGridSection = currGridSection.primaryGrid.rows.map(\r\n (v): GridSectionRowMetadataMapping => {\r\n return {\r\n gridSectionId: currGridSection.id,\r\n groupingKey: groupingKeyToFind,\r\n sortableContainerId: v.sortableInfo?.sortableContainerId ?? null,\r\n rowId: null,\r\n rowGroupingInfo: {\r\n isGroupedRow: v.groupingInfo?.isGroupedRow ?? false,\r\n order: v.groupingInfo?.order ?? null,\r\n groupingLevel: v.groupingInfo?.groupingLevel ?? null,\r\n groupingKey1: v.groupingInfo?.groupingKey1 ?? null,\r\n groupingKey2: v.groupingInfo?.groupingKey2 ?? null,\r\n groupingParent1Info: v.groupingInfo?.groupingParent1Info,\r\n groupingParent2Info: v.groupingInfo?.groupingParent2Info,\r\n globalCollapseResponseKey: v.groupingInfo?.globalCollapseResponseKey ?? null,\r\n globalCollapseTriggerKey: v.groupingInfo?.globalCollapseTriggerKey ?? null,\r\n },\r\n };\r\n },\r\n );\r\n\r\n gridSectionEntry.rowMetadataMappings = gridSectionEntry.rowMetadataMappings.filter((v) => {\r\n return allRowsInCurrGridSection.some(\r\n (m) =>\r\n normalizeNullOrUndefined(v.rowGroupingInfo.groupingKey1) ===\r\n normalizeNullOrUndefined(m.rowGroupingInfo.groupingKey1) &&\r\n normalizeNullOrUndefined(v.rowGroupingInfo.groupingKey2) ===\r\n normalizeNullOrUndefined(m.rowGroupingInfo.groupingKey2),\r\n );\r\n });\r\n }\r\n\r\n onCollapsedRowsChange(copy);\r\n });\r\n }, [gridSections, onCollapsedRowsChange]);\r\n\r\n const onRowClick = useCallback(\r\n // Collapse or expand the current row, and apply that collapse state to all of its sub rows\r\n (rowData: GridSectionRowMetadataMapping): void => {\r\n if (\r\n !rowData.rowGroupingInfo.groupingKey1 &&\r\n !rowData.rowGroupingInfo.groupingKey2 &&\r\n !rowData.rowGroupingInfo.globalCollapseTriggerKey\r\n ) {\r\n throw new Error(`Missing metadata for collapsible row trigger. Row Id: ${rowData.rowId}`);\r\n }\r\n\r\n const copy = [...collapsedRowsCopy.current];\r\n\r\n const gridSectionEntry = copy.find((v) => v.groupingKey === rowData.groupingKey);\r\n\r\n if (gridSectionEntry) {\r\n const existingItemIndex = gridSectionEntry.rowMetadataMappings.findIndex(\r\n (v) =>\r\n normalizeNullOrUndefined(v.rowGroupingInfo.groupingKey1) ===\r\n normalizeNullOrUndefined(rowData.rowGroupingInfo.groupingKey1) &&\r\n normalizeNullOrUndefined(v.rowGroupingInfo.groupingKey2) ===\r\n normalizeNullOrUndefined(rowData.rowGroupingInfo.groupingKey2) &&\r\n normalizeNullOrUndefined(v.rowGroupingInfo.globalCollapseResponseKey) ===\r\n normalizeNullOrUndefined(rowData.rowGroupingInfo.globalCollapseResponseKey) &&\r\n normalizeNullOrUndefined(v.rowGroupingInfo.globalCollapseTriggerKey) ===\r\n normalizeNullOrUndefined(rowData.rowGroupingInfo.globalCollapseTriggerKey),\r\n );\r\n\r\n gridSectionEntry.rowMetadataMappings = [...gridSectionEntry.rowMetadataMappings];\r\n\r\n if (existingItemIndex > -1) {\r\n gridSectionEntry.rowMetadataMappings.splice(existingItemIndex, 1);\r\n } else {\r\n gridSectionEntry.rowMetadataMappings.push({\r\n gridSectionId: rowData.gridSectionId,\r\n groupingKey: rowData.groupingKey,\r\n sortableContainerId: rowData.sortableContainerId,\r\n rowId: null,\r\n rowGroupingInfo: {\r\n isGroupedRow: rowData.rowGroupingInfo.isGroupedRow ?? false,\r\n order: rowData.rowGroupingInfo.order ?? null,\r\n groupingLevel: rowData.rowGroupingInfo.groupingLevel ?? null,\r\n groupingKey1: rowData.rowGroupingInfo.groupingKey1 ?? null,\r\n groupingKey2: rowData.rowGroupingInfo.groupingKey2 ?? null,\r\n groupingParent1Info: rowData.rowGroupingInfo.groupingParent1Info,\r\n groupingParent2Info: rowData.rowGroupingInfo.groupingParent2Info,\r\n globalCollapseResponseKey: rowData.rowGroupingInfo.globalCollapseResponseKey ?? null,\r\n globalCollapseTriggerKey: rowData.rowGroupingInfo.globalCollapseTriggerKey ?? null,\r\n },\r\n });\r\n }\r\n } else {\r\n // NOTE: We shouldn't run into this situation but log a warning just in case\r\n logger.logError(`Missing grid section for collapsible items: ${rowData.gridSectionId}`);\r\n }\r\n\r\n onCollapsedRowsChange(copy);\r\n },\r\n [logger, onCollapsedRowsChange],\r\n );\r\n\r\n const setPrimaryGridRef = useCallback((element: HTMLElement | null): void => {\r\n if (!element) {\r\n return;\r\n }\r\n\r\n if (!primaryGridReferences.current.some((v) => v.element === element)) {\r\n primaryGridReferences.current.push({\r\n element: element,\r\n });\r\n }\r\n }, []);\r\n\r\n const getPrimaryGridStyle = useCallback((): Dictionary => {\r\n let minWidth = '';\r\n\r\n if (typeof primaryGridsWidth === 'string' && (primaryGridsWidth as string).length) {\r\n minWidth = primaryGridsWidth;\r\n } else if (typeof primaryGridsWidth === 'number') {\r\n minWidth = `${primaryGridsWidth}px`;\r\n }\r\n\r\n return {\r\n minWidth: isFullWidth ? '100%' : minWidth,\r\n };\r\n }, [isFullWidth, primaryGridsWidth]);\r\n\r\n // We use a layout effect to respond to the rerenderId state variable change, and then recalculate things\r\n // before anything is rendered to the screen.\r\n // NOTE: Code inside a useLayoutEffect will run syncronously and block the UI from re-rendering until it's done.\r\n useLayoutEffect(() => {\r\n if (rerenderStatus === previousRerenderStatus.current) {\r\n return;\r\n }\r\n\r\n previousRerenderStatus.current = rerenderStatus;\r\n\r\n if (rerenderStatus !== null) {\r\n if (rerenderStatus.rowsChanged) {\r\n recalculateDimensions_RowHeights();\r\n }\r\n\r\n if (rerenderStatus.primaryGridColumnsChanged) {\r\n // Wrap this in a timeout so it runs on the next task, after the rows have rendered. This should do a quick calculation\r\n // and render the grid again with the new primary grid width, and this should all finish before the grid fades back in\r\n // after we set the rerender status to null.\r\n setTimeout(() => {\r\n recalculateDimensions_PrimaryGridWidths();\r\n });\r\n }\r\n\r\n setRerenderStatus(null);\r\n }\r\n }, [\r\n recalculateDimensions_PrimaryGridWidths,\r\n recalculateDimensions_RowHeights,\r\n rerenderStatus,\r\n setRerenderStatus,\r\n ]);\r\n\r\n // Run the dimension calculation code when this component mounts, but before anything is rendered to screen.\r\n // NOTE: Code inside a useLayoutEffect will run syncronously and block the UI from re-rendering until it's done.\r\n useLayoutEffect(() => {\r\n if (!gridIsInitialized.current) {\r\n gridIsInitialized.current = true;\r\n\r\n resetCalculatedDimensions_PrimaryGridWidths();\r\n resetCalculatedDimensions_RowHeights();\r\n\r\n setRerenderStatus({\r\n rerenderId: generateUuid(),\r\n // NOTE: Since we are initializing things, we don't have to do calculations on the columns width\r\n // the first time\r\n primaryGridColumnsChanged: true,\r\n rowsChanged: true,\r\n });\r\n\r\n initializeCollapsedStates();\r\n }\r\n }, [\r\n resetCalculatedDimensions_PrimaryGridWidths,\r\n resetCalculatedDimensions_RowHeights,\r\n initializeCollapsedStates,\r\n setRerenderStatus,\r\n ]);\r\n\r\n // NOTE: Code inside a useLayoutEffect will run syncronously and block the UI from re-rendering until it's done.\r\n useLayoutEffect(() => {\r\n let resizeEventCallback: NodeJS.Timeout | null = null;\r\n\r\n const resizeEventHandler = (): void => {\r\n // Delay firing any code since the resize events can come in rapid fire\r\n if (resizeEventCallback) {\r\n clearTimeout(resizeEventCallback);\r\n }\r\n\r\n resizeEventCallback = setTimeout(() => {\r\n recalculateDimensions_PrimaryGridWidths();\r\n }, 250);\r\n };\r\n\r\n window.addEventListener('resize', resizeEventHandler, { passive: true });\r\n\r\n return (): void => {\r\n window.removeEventListener('resize', resizeEventHandler);\r\n };\r\n }, [recalculateDimensions_PrimaryGridWidths]);\r\n\r\n // When the object reference changes, we want to recalculate the dimensions of things.\r\n // For performance reasons, we only perform certain logic when this code is told that the structure of the grid changed (ie. rows or columns\r\n // were added or removed).\r\n useEffect(() => {\r\n if (previousGridRerenderTriggerObject.current !== gridRerenderTriggerObject) {\r\n previousGridRerenderTriggerObject.current = gridRerenderTriggerObject;\r\n\r\n if (gridRerenderTriggerObject.rowsChanged ?? false) {\r\n resetCalculatedDimensions_RowHeights();\r\n }\r\n\r\n if (gridRerenderTriggerObject.primaryGridColumnsChanged ?? false) {\r\n resetCalculatedDimensions_PrimaryGridWidths();\r\n }\r\n\r\n setRerenderStatus({\r\n rerenderId: generateUuid(),\r\n // NOTE: Since we are initializing things, we don't have to do calculations on the columns\r\n // the first time\r\n primaryGridColumnsChanged: gridRerenderTriggerObject.primaryGridColumnsChanged ?? false,\r\n rowsChanged: gridRerenderTriggerObject.rowsChanged ?? false,\r\n });\r\n\r\n // Reset the grid row references so they get regenerated when the updated grid renders\r\n gridRowReferenceCollections.current = [];\r\n\r\n initializeCollapsedStates();\r\n }\r\n }, [\r\n gridSections,\r\n resetCalculatedDimensions_PrimaryGridWidths,\r\n resetCalculatedDimensions_RowHeights,\r\n initializeCollapsedStates,\r\n setRerenderStatus,\r\n gridRerenderTriggerObject,\r\n ]);\r\n\r\n // When the grid sections change, initialize or set the visual state collections\r\n useEffect(() => {\r\n // Verify that we have the same number of auxiliary / regular rows in the subgrids of each grid section.\r\n // We depend on these matching up for various functionality in this component so this is critical.\r\n gridSections.forEach((currGridSection) => {\r\n const auxiliaryRowsInPrimaryGrid = currGridSection.primaryGrid.auxiliaryRows.length;\r\n currGridSection.secondaryGrids.forEach((currSecondaryGrid) => {\r\n if (currSecondaryGrid.auxiliaryRows.length !== auxiliaryRowsInPrimaryGrid) {\r\n throw new Error(\r\n `Mismatched number of auxiliary rows in grid. Grid section ID: ${currGridSection.id}`,\r\n );\r\n }\r\n });\r\n\r\n const regularRowsInPrimaryGrid = currGridSection.primaryGrid.rows.length;\r\n currGridSection.secondaryGrids.forEach((currSecondaryGrid) => {\r\n if (currSecondaryGrid.rows.length !== regularRowsInPrimaryGrid) {\r\n throw new Error(\r\n `Mismatched number of regular rows in grid. Grid section ID: ${currGridSection.id}`,\r\n );\r\n }\r\n });\r\n });\r\n }, [gridSections]);\r\n\r\n // Listen for grid events\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n // Selected rows change event\r\n allSubscriptions.add(\r\n selectedRowsChange$.subscribe((v) => {\r\n selectedRowsCopy.current = v;\r\n }),\r\n );\r\n\r\n // Collapsed items change event\r\n allSubscriptions.add(\r\n collapsedRowsChange$.subscribe((v) => {\r\n collapsedRowsCopy.current = v;\r\n }),\r\n );\r\n\r\n // Row click event\r\n allSubscriptions.add(\r\n rowClick$.subscribe((v) => {\r\n onRowClick(v);\r\n }),\r\n );\r\n\r\n // Row checkbox click event\r\n allSubscriptions.add(\r\n rowCheckboxClick$.subscribe((v) => {\r\n onRowCheckboxClick(v);\r\n }),\r\n );\r\n\r\n // Set cell ref event\r\n allSubscriptions.add(\r\n setCellRef$.subscribe((v) => {\r\n setCellRef(v.gridSectionId, v.element, v.rowNumber);\r\n }),\r\n );\r\n\r\n // Dragging status changed\r\n allSubscriptions.add(\r\n dragStatusChanged$.subscribe((v) => {\r\n setIsDraggingItem(v);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [\r\n collapsedRowsChange$,\r\n onRowCheckboxClick,\r\n onRowClick,\r\n rowCheckboxClick$,\r\n rowClick$,\r\n rowMouseEnter$,\r\n rowMouseLeave$,\r\n selectedRowsChange$,\r\n setCellRef,\r\n setCellRef$,\r\n dragStatusChanged$,\r\n ]);\r\n\r\n // NOTE: The z-index of each grid section and each subgrid inside of each grid section is very important for a number of reasons.\r\n // We have various functionality in the grid that we support, such as cells containing dropdowns and custom right click context menus,\r\n // \"floating\" cells, etc.\r\n // The behavior we would like is that things will cascade from the top left downward to the bottom right as far as z-index is concerned.\r\n // _______ _______ _______\r\n // | 1000 | | 999 | | 998 |\r\n // ------- ------- -------\r\n // _______ _______ _______\r\n // | 950 | | 949 | | 948 |\r\n // ------- ------- -------\r\n\r\n // NOTE: z-indices on a grid section should be descending from left to right, but even the lowest number should be greater than any on the grid section below it\r\n\r\n return useMemo(() => {\r\n return (\r\n \r\n
    \r\n {gridSections.map((currGridSection, gridSectionIndex) => {\r\n // We will start with a base number and go down by 50 each time.\r\n // NOTE: This assumes that we will not have more than 50 subgrids inside of a grid section.\r\n\r\n const gridSectionZIndexBase = GeneralConstants.UI_ZINDEXBASE - gridSectionIndex * 50;\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n })}\r\n
    \r\n\r\n \r\n \r\n );\r\n }, [\r\n getPrimaryGridStyle,\r\n gridSections,\r\n isFullWidth,\r\n isReadOnly,\r\n onKeyDown,\r\n rerenderStatus,\r\n setPrimaryGridRef,\r\n isDraggingItem,\r\n ]);\r\n};\r\n\r\nconst BTGridContainer: React.FC = (props) => {\r\n return ;\r\n};\r\n\r\nexport default BTGridContainer;\r\n","import React, { useContext } from 'react';\r\nimport { Observable } from 'rxjs';\r\nimport { Adjustment } from '../../../../classes/odata/adjustment';\r\nimport { Bidder } from '../../../../classes/odata/bidder';\r\nimport {\r\n useObservable,\r\n useObservableWithBehaviorSubject,\r\n useObservableWithValue,\r\n} from '../../../../hooks/observables/useObservable';\r\n\r\ninterface LineItemBidInfo {\r\n bidderId: string;\r\n bidPackageLineItemId: string;\r\n}\r\n\r\ninterface RequirementFulfillmentBidInfo {\r\n requirementId: string;\r\n bidderId: string;\r\n}\r\n\r\ninterface BidPackagePageContextInterface {\r\n // Adjustments\r\n adjustmentBlur$: Observable;\r\n adjustmentChange$: Observable;\r\n adjustmentNotesOpen$: Observable<{ alternateId: string | null; bidderId: string } | null>;\r\n adjustmentNotesSave$: Observable;\r\n\r\n adjustment_Blur: (bidValue: AdjustmentBidValue) => void;\r\n adjustment_Change: (bidValue: AdjustmentBidValue) => void;\r\n adjustment_OpenNote: (\r\n adjustmentData: { alternateId: string | null; bidderId: string } | null,\r\n ) => void;\r\n adjustment_SaveNote: (adjustment: Adjustment) => void;\r\n\r\n // Bidders\r\n bidderDelete$: Observable;\r\n bidderEdit$: Observable;\r\n bidderEditDocuments$: Observable;\r\n bidderEditNotes$: Observable;\r\n bidderSelect$: Observable;\r\n bidderShowInfo$: Observable;\r\n biddersAdd$: Observable;\r\n\r\n bidder_Delete: (bidder: Bidder) => void;\r\n bidder_Edit: (bidder: Bidder) => void;\r\n bidder_EditDocuments: (bidder: Bidder) => void;\r\n bidder_EditNotes: (bidder: Bidder) => void;\r\n bidder_Select: (bidderCompanyName: string | null) => void;\r\n bidder_ShowInfo: (bidder: Bidder) => void;\r\n bidders_Add: () => void;\r\n\r\n // Line Items\r\n lineItemBlur$: Observable;\r\n lineItemChange$: Observable;\r\n lineItemsAdd$: Observable;\r\n lineItemDelete$: Observable;\r\n lineItemsDelete$: Observable; // Takes an alternate ID as a parameter\r\n lineItemEdit$: Observable;\r\n lineItemsEdit$: Observable; // Takes an alternate ID as a parameter\r\n\r\n lineItem_Blur: (newLineItem: LineItemValue) => void;\r\n lineItem_Change: (newLineItem: LineItemValue) => void;\r\n lineItem_Delete: (idOfLineItemToDelete: string) => void;\r\n lineItem_Edit: (idOfLineItemToEdit: string) => void;\r\n lineItems_Add: (alternateName: string | null) => void;\r\n lineItems_Delete: (alternateId: string | null) => void;\r\n lineItems_Edit: (alternateId: string | null) => void;\r\n\r\n // Line Item Bids\r\n lineItemBidBlur$: Observable;\r\n lineItemBidChange$: Observable;\r\n lineItemBidFocus$: Observable;\r\n\r\n lineItemBid_Blur: (bidValue: LineItemBidValue) => void;\r\n lineItemBid_Change: (bidValue: LineItemBidValue) => void;\r\n lineItemBid_Focus: (bidInfo: LineItemBidInfo) => void;\r\n\r\n // Line Item Rollup Bids\r\n lineItemRollupBidBlur$: Observable;\r\n lineItemRollupBidChange$: Observable;\r\n\r\n lineItemRollupBid_Blur: (bidValue: LineItemRollupBidValue) => void;\r\n lineItemRollupBid_Change: (bidValue: LineItemRollupBidValue) => void;\r\n\r\n // Requirement Fulfillments\r\n requirementFulfillmentBlur$: Observable;\r\n requirementFulfillmentChange$: Observable;\r\n requirementFulfillmentFocus$: Observable;\r\n\r\n requirementFulfillment_Blur: (bidValue: RequirementFulfillmentBidValue) => void;\r\n requirementFulfillment_Change: (bidValue: RequirementFulfillmentBidValue) => void;\r\n requirementFulfillment_Focus: (bidInfo: RequirementFulfillmentBidInfo) => void;\r\n\r\n // Other observables\r\n bidPackageNotes$: Observable;\r\n keyboardShortcutsInfoIsOpen$: Observable;\r\n lockBidPackage$: Observable;\r\n selectedLineItemsMappings$: Observable>;\r\n viewProjectInfo$: Observable;\r\n\r\n // Functions\r\n bidPackageNotes_Open: (newValue: string) => void;\r\n keyboardShortcutsInfoIsOpen_Change: (newValue: boolean) => void;\r\n lockBidPackage_Change: () => void;\r\n selectedLineItemsMappings_Change: (newValue: Record) => void;\r\n viewProjectInfo_Open: () => void;\r\n}\r\n\r\nconst BidPackagePageContext = React.createContext(\r\n {} as BidPackagePageContextInterface,\r\n);\r\n\r\nconst BidPackagePageContextProvider: React.FC = ({ children }) => {\r\n // Adjustments\r\n const [adjustmentNotesOpen$, adjustment_OpenNote] = useObservableWithValue<{\r\n alternateId: string | null;\r\n bidderId: string;\r\n } | null>();\r\n const [adjustmentNotesSave$, adjustment_SaveNote] = useObservableWithValue();\r\n const [adjustmentChange$, adjustment_Change] = useObservableWithValue();\r\n const [adjustmentBlur$, adjustment_Blur] = useObservableWithValue();\r\n\r\n // Bidders\r\n const [bidderEditDocuments$, bidder_EditDocuments] = useObservableWithValue();\r\n const [bidderEditNotes$, bidder_EditNotes] = useObservableWithValue();\r\n const [bidderShowInfo$, bidder_ShowInfo] = useObservableWithValue();\r\n\r\n const [bidderDelete$, bidder_Delete] = useObservableWithValue();\r\n const [bidderEdit$, bidder_Edit] = useObservableWithValue();\r\n const [bidderSelect$, bidder_Select] = useObservableWithValue();\r\n const [biddersAdd$, bidders_Add] = useObservable();\r\n\r\n // Line Items\r\n const [lineItemChange$, lineItem_Change] = useObservableWithValue();\r\n const [lineItemBlur$, lineItem_Blur] = useObservableWithValue();\r\n\r\n const [lineItemsAdd$, lineItems_Add] = useObservableWithValue();\r\n const [lineItemDelete$, lineItem_Delete] = useObservableWithValue();\r\n const [lineItemsDelete$, lineItems_Delete] = useObservableWithValue();\r\n const [lineItemEdit$, lineItem_Edit] = useObservableWithValue();\r\n const [lineItemsEdit$, lineItems_Edit] = useObservableWithValue();\r\n\r\n // Line Item Bids\r\n const [lineItemBidChange$, lineItemBid_Change] = useObservableWithValue();\r\n const [lineItemBidBlur$, lineItemBid_Blur] = useObservableWithValue();\r\n const [lineItemBidFocus$, lineItemBid_Focus] = useObservableWithValue();\r\n\r\n // Line Item Rollup Bids\r\n const [lineItemRollupBidChange$, lineItemRollupBid_Change] = useObservableWithValue<\r\n LineItemRollupBidValue\r\n >();\r\n const [lineItemRollupBidBlur$, lineItemRollupBid_Blur] = useObservableWithValue<\r\n LineItemRollupBidValue\r\n >();\r\n\r\n // Requirement Fulfillments\r\n const [requirementFulfillmentBlur$, requirementFulfillment_Blur] = useObservableWithValue<\r\n RequirementFulfillmentBidValue\r\n >();\r\n const [requirementFulfillmentChange$, requirementFulfillment_Change] = useObservableWithValue<\r\n RequirementFulfillmentBidValue\r\n >();\r\n const [requirementFulfillmentFocus$, requirementFulfillment_Focus] = useObservableWithValue<\r\n RequirementFulfillmentBidInfo\r\n >();\r\n\r\n // Other\r\n const [lockBidPackage$, lockBidPackage_Change] = useObservable();\r\n\r\n const [bidPackageNotes$, bidPackageNotes_Open] = useObservableWithValue();\r\n\r\n const [keyboardShortcutsInfoIsOpen$, keyboardShortcutsInfoIsOpen_Change] = useObservableWithValue<\r\n boolean\r\n >();\r\n\r\n // NOTE: The selected line items mapping is underpinned by a behavior subject, which will broadcast\r\n // its value immediately upon subscription by calling code\r\n const [\r\n selectedLineItemsMappings$,\r\n selectedLineItemsMappings_Change,\r\n ] = useObservableWithBehaviorSubject>({});\r\n\r\n const [viewProjectInfo$, viewProjectInfo_Open] = useObservable();\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nexport const useBidPackagePageContext = (): BidPackagePageContextInterface =>\r\n useContext(BidPackagePageContext);\r\n\r\nexport default useBidPackagePageContext;\r\n\r\nexport { BidPackagePageContextProvider };\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class AddLineItemToBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public description: string,\r\n public quantity: number,\r\n public unitOfMeasure: string,\r\n public unitPrice: number,\r\n public metadata: Metadata[],\r\n public alternateName: string | null | undefined,\r\n ) {\r\n super('DESTINI.BidDay.Commands.BidPackages.AddLineItemToBidPackage', '', 'none');\r\n }\r\n}\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class UpdateBidPackageLineItemCommand extends CommandBase {\r\n public bidPackageId: string;\r\n public lineItemId: string;\r\n public description?: string;\r\n public quantity?: number;\r\n public unitOfMeasure?: string;\r\n public unitPrice?: number;\r\n public metadata?: Metadata[];\r\n\r\n constructor(\r\n bidPackageId: string,\r\n lineItemId: string,\r\n description?: string,\r\n quantity?: number,\r\n unitOfMeasure?: string,\r\n unitPrice?: number,\r\n metadata?: Metadata[],\r\n ) {\r\n super('DESTINI.BidDay.Commands.BidPackages.UpdateBidPackageLineItem', '', 'none');\r\n this.bidPackageId = bidPackageId;\r\n this.lineItemId = lineItemId;\r\n this.description = description;\r\n this.quantity = quantity;\r\n this.unitOfMeasure = unitOfMeasure;\r\n this.unitPrice = unitPrice;\r\n this.metadata = metadata;\r\n }\r\n}\r\n","import {\r\n AutoComplete,\r\n AutoCompleteBlurEvent,\r\n AutoCompleteChangeEvent,\r\n} from '@progress/kendo-react-dropdowns';\r\nimport { GridCellProps } from '@progress/kendo-react-grid';\r\nimport React, { RefObject, useCallback, useEffect, useRef } from 'react';\r\nimport GeneralConstants from '../../../../constants/general';\r\n\r\ninterface BTItemsManagerGridAutoCompleteCellProps extends GridCellProps {\r\n listAnchor: RefObject;\r\n required?: boolean;\r\n listValues: string[];\r\n testIdPrefix: string;\r\n maxLength?: number;\r\n addListValue: (newValue: string) => string | undefined;\r\n onPaste?: React.ClipboardEventHandler;\r\n}\r\n\r\nconst BTItemsManagerGridAutoCompleteCell: React.FC = (\r\n props,\r\n) => {\r\n const inputRef: React.MutableRefObject = useRef(null);\r\n const autoCompleteComponent: React.MutableRefObject = useRef(null);\r\n\r\n const handleChange = useCallback(\r\n (e: AutoCompleteChangeEvent) => {\r\n if (props.onChange) {\r\n const newValue = e.target.value ?? '';\r\n\r\n props.onChange({ ...props, value: newValue, syntheticEvent: e.syntheticEvent });\r\n }\r\n },\r\n [props],\r\n );\r\n\r\n const handleBlur = useCallback(\r\n (e: AutoCompleteBlurEvent) => {\r\n let newValue = e.target.value ?? '';\r\n if (newValue.trim().length > 0) {\r\n const existingValue = props.addListValue(newValue);\r\n if (existingValue) {\r\n newValue = existingValue;\r\n }\r\n }\r\n },\r\n [props],\r\n );\r\n\r\n useEffect(() => {\r\n const currentInput = inputRef.current;\r\n\r\n const onKeyDownHandler = (e: KeyboardEvent) => {\r\n // When enter is pressed, stop the event from bubbling, otherwise it will select the first item in the list\r\n if (e.key.toUpperCase() === GeneralConstants.KEY_ENTER.toUpperCase()) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n // Close the suggestions\r\n autoCompleteComponent.current!.setState({ opened: false });\r\n }\r\n };\r\n\r\n const onPasteHandler = () => {\r\n // Close the suggestions when the user pastes something\r\n setTimeout(() => {\r\n autoCompleteComponent.current!.setState({ opened: false });\r\n });\r\n };\r\n\r\n if (currentInput) {\r\n currentInput.addEventListener('keydown', onKeyDownHandler);\r\n currentInput.addEventListener('paste', onPasteHandler);\r\n }\r\n\r\n return () => {\r\n currentInput?.removeEventListener('keydown', onKeyDownHandler);\r\n currentInput?.removeEventListener('paste', onPasteHandler);\r\n };\r\n }, []);\r\n\r\n const id = `${props.testIdPrefix}-${props.field}-${props.dataIndex}`;\r\n\r\n return (\r\n {\r\n if (props.onPaste) {\r\n props.onPaste(e);\r\n }\r\n }}\r\n >\r\n {\r\n // Open the suggestions on focus\r\n autoCompleteComponent.current!.setState({ opened: true });\r\n\r\n (e.nativeEvent.target as HTMLInputElement).select();\r\n }}\r\n ref={(e) => {\r\n if (e) {\r\n autoCompleteComponent.current = e;\r\n inputRef.current = (e.element as unknown) as HTMLInputElement;\r\n }\r\n\r\n // Add in a custom attribute for the test ID\r\n if (e?.element && !e.element?.getAttribute('data-testid')) {\r\n e.element.setAttribute('data-testid', id);\r\n }\r\n // Set a maxLength if one is provided\r\n if (e?.element && props.maxLength) {\r\n const input = e.element.querySelector('input[type=\"text\"]');\r\n if (input) {\r\n input.setAttribute('maxLength', props.maxLength.toString());\r\n }\r\n }\r\n }}\r\n />\r\n \r\n );\r\n};\r\n\r\nexport default BTItemsManagerGridAutoCompleteCell;\r\n","import { DropDownList, DropDownListChangeEvent } from '@progress/kendo-react-dropdowns';\r\nimport { GridCellProps } from '@progress/kendo-react-grid';\r\nimport React, { RefObject, useCallback } from 'react';\r\n\r\ninterface BTItemsManagerGridDropdownCellProps extends GridCellProps {\r\n listAnchor: RefObject;\r\n required?: boolean;\r\n listValues: unknown[];\r\n textField?: string;\r\n dataItemKey?: string;\r\n testIdPrefix: string;\r\n onPaste?: React.ClipboardEventHandler;\r\n}\r\n\r\nconst BTItemsManagerGridDropdownCell: React.FC = (props) => {\r\n const handleChange = useCallback(\r\n (e: DropDownListChangeEvent) => {\r\n if (props.onChange) {\r\n props.onChange({ ...props, value: e.target.value, syntheticEvent: e.syntheticEvent });\r\n }\r\n },\r\n [props],\r\n );\r\n\r\n const id = `${props.testIdPrefix}-${props.field}-${props.dataIndex}`;\r\n\r\n return (\r\n {\r\n if (props.onPaste) {\r\n props.onPaste(e);\r\n }\r\n }}\r\n >\r\n {\r\n // Add in a custom attribute for the test ID\r\n if (e?.element && !e.element?.getAttribute('data-testid')) {\r\n e.element.setAttribute('data-testid', id);\r\n }\r\n }}\r\n />\r\n \r\n );\r\n};\r\n\r\nexport default BTItemsManagerGridDropdownCell;\r\n","import { GridCellProps } from '@progress/kendo-react-grid';\r\nimport { NumericTextBoxChangeEvent } from '@progress/kendo-react-inputs';\r\nimport React, { useCallback } from 'react';\r\nimport BTNumericInput from '../../inputs/BTNumericInput';\r\n\r\ninterface BTItemsManagerGridNumericCellProps extends GridCellProps {\r\n required?: boolean;\r\n testIdPrefix: string;\r\n onPaste?: React.ClipboardEventHandler;\r\n}\r\n\r\nconst BTItemsManagerGridNumericCell: React.FC = ({\r\n testIdPrefix,\r\n field,\r\n dataIndex,\r\n dataItem,\r\n required,\r\n onPaste,\r\n ...props\r\n}) => {\r\n const handleChange = useCallback(\r\n (e: NumericTextBoxChangeEvent) => {\r\n if (props.onChange) {\r\n props.onChange({\r\n field,\r\n dataIndex,\r\n dataItem,\r\n value: e.target.value,\r\n syntheticEvent: e.syntheticEvent,\r\n });\r\n }\r\n },\r\n [dataIndex, dataItem, field, props],\r\n );\r\n\r\n // Checks to see if n5 (5-precision number) or c5 (5-precision currency) are the provided formats\r\n const isExtendedPrecisionFormat = props.format === 'n5' || props.format === 'c5';\r\n\r\n return (\r\n {\r\n if (onPaste) {\r\n onPaste(e);\r\n }\r\n }}\r\n >\r\n {/* NOTE: The BTNumericInput will set the data-testid based on its \"id\" prop */}\r\n \r\n \r\n );\r\n};\r\n\r\nexport default BTItemsManagerGridNumericCell;\r\n","import { GridCellProps } from '@progress/kendo-react-grid';\r\nimport { Input } from '@progress/kendo-react-inputs';\r\nimport { InputChangeEvent } from '@progress/kendo-react-inputs/dist/npm/input/interfaces/InputChangeEvent';\r\nimport React, { useCallback, useRef } from 'react';\r\nimport useFocusOnRender from '../../forms/hooks/useFocusOnRender';\r\n\r\nexport type GridCellValidatorFunction = (currValue: string) => boolean;\r\n\r\ninterface BTItemsManagerGridTextCellProps extends GridCellProps {\r\n required?: boolean;\r\n testIdPrefix: string;\r\n autoFocus?: boolean;\r\n maxLength?: number;\r\n validationFn?: (currValue: string) => boolean;\r\n onPaste?: React.ClipboardEventHandler;\r\n}\r\n\r\nconst BTItemsManagerGridTextCell: React.FC = (props) => {\r\n const handleChange = useCallback(\r\n (e: InputChangeEvent) => {\r\n if (props.onChange) {\r\n props.onChange({\r\n ...props,\r\n value: e.target.value,\r\n syntheticEvent: e.syntheticEvent,\r\n });\r\n }\r\n },\r\n [props],\r\n );\r\n\r\n const dataValue = props.field && props.dataItem[props.field] ? props.dataItem[props.field] : '';\r\n\r\n const inputRef = useRef();\r\n useFocusOnRender({ autoFocus: props.autoFocus || false, inputRef: inputRef });\r\n\r\n const id = `${props.testIdPrefix}-${props.field}-${props.dataIndex}`;\r\n\r\n return (\r\n {\r\n if (props.onPaste) {\r\n props.onPaste(e);\r\n }\r\n }}\r\n >\r\n {\r\n // Add in a custom attribute for the test ID\r\n if (e?.element && !e.element?.getAttribute('data-testid')) {\r\n inputRef.current = e.element!;\r\n e.element.setAttribute('data-testid', id);\r\n }\r\n }}\r\n />\r\n \r\n );\r\n};\r\n\r\nexport default BTItemsManagerGridTextCell;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport {\r\n Grid,\r\n GridCellProps,\r\n GridColumn,\r\n GridItemChangeEvent,\r\n GridNoRecords,\r\n GridToolbar,\r\n} from '@progress/kendo-react-grid';\r\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { AddLineItemToBidPackageCommand } from '../../../../../classes/commands/bid-packages/add-line-item-to-bid-package-command';\r\nimport { UpdateBidPackageLineItemCommand } from '../../../../../classes/commands/bid-packages/update-bid-package-line-item-command';\r\nimport GeneralConstants from '../../../../../constants/general';\r\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\r\nimport { ProjectApi } from '../../../../../services';\r\nimport { useLogger } from '../../../../../services/logger/Logger';\r\nimport {\r\n areTrimmedStringsEqual,\r\n getSanitizedExcelRows,\r\n isEmptyOrWhitespace,\r\n removeNonNumericCharsFromString,\r\n} from '../../../../../utils/strings';\r\nimport { generateUuid } from '../../../../../utils/uuid';\r\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\r\nimport FormErrorContainer from '../../../../common-page-components/forms/form-error-container/FormErrorContainer';\r\nimport FormFooter from '../../../../common-page-components/forms/FormFooter';\r\nimport BTItemsManagerGridAutoCompleteCell from '../../../../common-page-components/items-manager-grid/cells/BTItemsManagerGridAutoCompleteCell';\r\nimport BTItemsManagerGridDropdownCell from '../../../../common-page-components/items-manager-grid/cells/BTItemsManagerGridDropdownCell';\r\nimport BTItemsManagerGridNumericCell from '../../../../common-page-components/items-manager-grid/cells/BTItemsManagerGridNumericCell';\r\nimport BTItemsManagerGridTextCell from '../../../../common-page-components/items-manager-grid/cells/BTItemsManagerGridTextCell';\r\nimport './AddEditLineItemsForm.scss';\r\n\r\ninterface Props {\r\n projectId: string;\r\n bidPackageId: string;\r\n mode: 'add' | 'edit';\r\n unitsOfMeasure: string[];\r\n lineItemRollup1: string;\r\n lineItemRollup2?: string;\r\n alternateName: string | null;\r\n lineItemsToEdit?: LineItemValue[];\r\n onSaveClick: (commands: ICommand[]) => void;\r\n onDiscardClick: (lineItemsToEdit: LineItemInfo[]) => void;\r\n onFormTouch?: (itemsChanged: boolean) => void;\r\n}\r\n\r\ninterface ParsedRowData {\r\n description: string;\r\n quantity: number;\r\n unit: string;\r\n unitPrice: number;\r\n metadata1: string;\r\n metadata2: string;\r\n}\r\n\r\nexport interface LineItemInfo {\r\n id: string;\r\n description: string;\r\n quantity: number;\r\n unit: string;\r\n unitPrice: number;\r\n metadata1: string;\r\n metadata2: string;\r\n inEdit: boolean;\r\n changed: boolean;\r\n metadataChanged: boolean;\r\n}\r\n\r\nconst AddEditLineItemsForm: React.FC = ({\r\n projectId,\r\n bidPackageId,\r\n mode,\r\n unitsOfMeasure,\r\n lineItemRollup1,\r\n lineItemRollup2,\r\n alternateName,\r\n lineItemsToEdit,\r\n onSaveClick,\r\n onDiscardClick,\r\n onFormTouch,\r\n}) => {\r\n const isAddMode = mode === 'add';\r\n\r\n const { t } = useTranslation();\r\n const logger = useLogger();\r\n\r\n const [errors, setErrors] = useState([]);\r\n\r\n const [level1Classifications, setLevel1Classifications] = useState([]);\r\n const [level2Classifications, setLevel2Classifications] = useState([]);\r\n\r\n const fetchMetadata = useCallback(async () => {\r\n try {\r\n const projectMetadata = await ProjectApi.getLineItemMetadataForProject(projectId);\r\n setLevel1Classifications(\r\n projectMetadata.filter((m) => m.name === lineItemRollup1).map((m) => m.value),\r\n );\r\n if (lineItemRollup2) {\r\n setLevel2Classifications(\r\n projectMetadata.filter((m) => m.name === lineItemRollup2).map((m) => m.value),\r\n );\r\n }\r\n } catch (error) {\r\n logger.logError(error);\r\n }\r\n }, [\r\n projectId,\r\n lineItemRollup1,\r\n lineItemRollup2,\r\n setLevel1Classifications,\r\n setLevel2Classifications,\r\n logger,\r\n ]);\r\n\r\n useEffect(() => {\r\n fetchMetadata();\r\n }, [fetchMetadata]);\r\n\r\n const [lineItems, setLineItems] = useState(\r\n !isAddMode\r\n ? lineItemsToEdit?.map((li) => {\r\n const lineItem: LineItemInfo = {\r\n id: li.id ?? generateUuid(),\r\n description: li.description ?? '',\r\n quantity: li.quantity ?? 0,\r\n unit: li.quantityUnitOfMeasure ?? '',\r\n unitPrice: li.unitPrice ?? 0,\r\n metadata1: li.metadata?.find((m) => m.name === lineItemRollup1)?.value ?? '',\r\n metadata2: li.metadata?.find((m) => m.name === lineItemRollup2)?.value ?? '',\r\n inEdit: true,\r\n changed: false,\r\n metadataChanged: false,\r\n };\r\n return lineItem;\r\n }) ?? []\r\n : [],\r\n );\r\n\r\n useEffect(() => {\r\n if (onFormTouch) {\r\n onFormTouch(lineItems.some((v) => v.changed));\r\n }\r\n }, [lineItems, onFormTouch]);\r\n\r\n const addNewLineItem = useCallback(() => {\r\n if (!isAddMode) {\r\n return;\r\n }\r\n\r\n const newLineItem: LineItemInfo = {\r\n id: generateUuid(),\r\n description: '',\r\n quantity: 0,\r\n unit: '',\r\n unitPrice: 0,\r\n metadata1: '',\r\n metadata2: '',\r\n inEdit: true,\r\n changed: false,\r\n metadataChanged: false,\r\n };\r\n\r\n setLineItems((v) => {\r\n return [...v, newLineItem];\r\n });\r\n }, [isAddMode]);\r\n\r\n const removeLineItem = useCallback((lineItem: LineItemInfo) => {\r\n setLineItems((v) => {\r\n return v.filter((li) => !(li.id === lineItem.id));\r\n });\r\n }, []);\r\n\r\n const addNewLevel1Classification = useCallback(\r\n (classification: string): string | undefined => {\r\n const existingValue = level1Classifications.find(\r\n (c) => c.toLowerCase() === classification.toLowerCase(),\r\n );\r\n if (existingValue) {\r\n return existingValue;\r\n }\r\n level1Classifications.push(classification);\r\n setLevel1Classifications(level1Classifications);\r\n },\r\n [level1Classifications, setLevel1Classifications],\r\n );\r\n\r\n const addNewLevel2Classification = useCallback(\r\n (classification: string): string | undefined => {\r\n const existingValue = level2Classifications.find(\r\n (c) => c.toLowerCase() === classification.toLowerCase(),\r\n );\r\n if (existingValue) {\r\n return existingValue;\r\n }\r\n level2Classifications.push(classification);\r\n setLevel2Classifications(level2Classifications);\r\n },\r\n [level2Classifications, setLevel2Classifications],\r\n );\r\n\r\n const handlePaste = useCallback(\r\n (e: React.ClipboardEvent) => {\r\n const clipboardData = e.clipboardData.getData('text');\r\n const rows = getSanitizedExcelRows(clipboardData);\r\n\r\n // If the user is pasting in text without any special characters that we parse, let them paste it\r\n if (rows?.length === 1 && rows[0].length === 1) {\r\n return;\r\n }\r\n\r\n // Prevent the event from bubbling, since we are handling the paste event entirely here\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n // For certain cells, we tack on the column index of the cell\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const eventAsAny = e as any;\r\n const columnIndexOfOriginCell = eventAsAny.columnIndex ?? null;\r\n const rowIndexOfOriginCell = eventAsAny.rowIndex ?? null;\r\n\r\n const parseLineItemInputsFromRow = (rowData: string[]): ParsedRowData => {\r\n const returnValue: ParsedRowData = {\r\n description: rowData[0] || '',\r\n quantity: parseFloat(removeNonNumericCharsFromString(rowData[1] || '')),\r\n unit:\r\n unitsOfMeasure.find((unitOfMeasure) =>\r\n areTrimmedStringsEqual(unitOfMeasure, rowData[2] ?? ''),\r\n ) ?? '',\r\n unitPrice: parseFloat(removeNonNumericCharsFromString(rowData[3] || '')),\r\n metadata1: rowData[4] ?? '',\r\n metadata2: rowData[5] ?? '',\r\n };\r\n\r\n if (isNaN(returnValue.quantity)) {\r\n returnValue.quantity = 0;\r\n }\r\n\r\n if (isNaN(returnValue.unitPrice)) {\r\n returnValue.unitPrice = 0;\r\n }\r\n\r\n return returnValue;\r\n };\r\n\r\n // If the user pasted into a cell in an existing row, and the clipboard contained a single row of data with multiple cells,\r\n // paste the data starting at the specified cell, on the specified row\r\n if (columnIndexOfOriginCell >= 0 && rows?.length === 1 && rows[0].length > 1) {\r\n // Pad the rows collection for the cells prior to the one that was pasted into\r\n for (let i = columnIndexOfOriginCell - 1; i >= 0; i--) {\r\n switch (i) {\r\n case 0:\r\n rows[0].unshift(lineItems[rowIndexOfOriginCell]?.description || '');\r\n break;\r\n\r\n case 1:\r\n rows[0].unshift(lineItems[rowIndexOfOriginCell]?.quantity?.toString() || '');\r\n break;\r\n\r\n case 2:\r\n rows[0].unshift(lineItems[rowIndexOfOriginCell]?.unit || '');\r\n break;\r\n\r\n case 3:\r\n rows[0].unshift(lineItems[rowIndexOfOriginCell]?.unitPrice?.toString() || '');\r\n break;\r\n\r\n case 4:\r\n rows[0].unshift(lineItems[rowIndexOfOriginCell]?.metadata1 || '');\r\n break;\r\n\r\n case 5:\r\n rows[0].unshift(lineItems[rowIndexOfOriginCell]?.metadata2 || '');\r\n break;\r\n }\r\n }\r\n\r\n const parsedRowData = parseLineItemInputsFromRow(rows[0]);\r\n\r\n // Update the existing line item\r\n if (rowIndexOfOriginCell !== null) {\r\n setLineItems((currLineItems) => {\r\n const newLineItems = [...currLineItems];\r\n\r\n // NOTE: The grid sometimes reports a row index of 0 when it's empty, so handle this weirdness\r\n if (newLineItems[rowIndexOfOriginCell]) {\r\n newLineItems[rowIndexOfOriginCell].changed = true;\r\n\r\n newLineItems[rowIndexOfOriginCell] = {\r\n ...newLineItems[rowIndexOfOriginCell],\r\n ...parsedRowData,\r\n };\r\n } else {\r\n newLineItems.push({\r\n id: generateUuid(),\r\n ...parsedRowData,\r\n inEdit: true,\r\n changed: true,\r\n metadataChanged:\r\n parsedRowData.metadata1.length > 0 || parsedRowData.metadata2.length > 0,\r\n });\r\n }\r\n\r\n return newLineItems;\r\n });\r\n\r\n // Blur the input that triggered the paste event, so Kendo displays the new values\r\n if (e.target && (e.target as HTMLInputElement).blur) {\r\n (e.target as HTMLInputElement).blur();\r\n }\r\n\r\n return;\r\n }\r\n }\r\n\r\n // NOTE: If we are in edit mode, we let the user paste multiple cells into a row, but we don't allow pasting multiple rows\r\n // of data, as we don't want to be able to add bidders in edit mode\r\n if (!isAddMode && (rows?.length || 0) > 1) {\r\n return;\r\n }\r\n\r\n if (rows) {\r\n const result = rows.map((currRow) => {\r\n const parsedRowDataForCurrRow = parseLineItemInputsFromRow(currRow);\r\n\r\n const returnValue: LineItemInfo = {\r\n id: generateUuid(),\r\n ...parsedRowDataForCurrRow,\r\n inEdit: true,\r\n changed: true,\r\n metadataChanged:\r\n parsedRowDataForCurrRow.metadata1.length > 0 ||\r\n parsedRowDataForCurrRow.metadata2.length > 0,\r\n };\r\n\r\n return returnValue;\r\n });\r\n\r\n // Add in the new rows and remove any empty rows\r\n setLineItems((currLineItems) => {\r\n return currLineItems.concat(result).filter((v) => {\r\n return (\r\n !isEmptyOrWhitespace(v.description) ||\r\n v.quantity ||\r\n !isEmptyOrWhitespace(v.unit) ||\r\n v.unitPrice ||\r\n !isEmptyOrWhitespace(v.metadata1) ||\r\n !isEmptyOrWhitespace(v.metadata2)\r\n );\r\n });\r\n });\r\n\r\n // Blur the input that triggered the paste event, so Kendo displays the new values\r\n if (e.target && (e.target as HTMLInputElement).blur) {\r\n (e.target as HTMLInputElement).blur();\r\n }\r\n }\r\n },\r\n [isAddMode, lineItems, unitsOfMeasure],\r\n );\r\n\r\n const getCommands = useCallback((): ICommand[] => {\r\n if (isAddMode) {\r\n const commands = lineItems.map((li) => {\r\n const command = new AddLineItemToBidPackageCommand(\r\n bidPackageId,\r\n li.description.trim(),\r\n li.quantity,\r\n li.unit,\r\n li.unitPrice,\r\n [],\r\n alternateName,\r\n );\r\n if (li.metadata1?.trim().length > 0) {\r\n command.metadata.push({ name: lineItemRollup1, value: li.metadata1.trim() });\r\n }\r\n if (lineItemRollup2 && li.metadata2?.trim().length > 0) {\r\n command.metadata.push({ name: lineItemRollup2, value: li.metadata2.trim() });\r\n }\r\n return command;\r\n });\r\n return commands;\r\n } else {\r\n const commands = lineItems\r\n .filter((li) => li.changed)\r\n .map((li) => {\r\n const originalLineItem = lineItemsToEdit?.find((oli) => oli.id === li.id);\r\n const updatedLineItem = new UpdateBidPackageLineItemCommand(\r\n bidPackageId,\r\n li.id,\r\n !(li.description === originalLineItem?.description)\r\n ? li.description?.trim()\r\n : undefined,\r\n !(li.quantity === originalLineItem?.quantity) ? li.quantity : undefined,\r\n !(li.unit === originalLineItem?.quantityUnitOfMeasure) ? li.unit : undefined,\r\n !(li.unitPrice === originalLineItem?.unitPrice) ? li.unitPrice : undefined,\r\n !li.metadataChanged\r\n ? undefined\r\n : originalLineItem?.metadata\r\n // Filter out line item rollup values since they are added in the if statements below\r\n ?.filter((m) => m.name !== lineItemRollup1 && m.name !== lineItemRollup2)\r\n .map((m) => ({ name: m.name!, value: m.value! })) ?? undefined,\r\n );\r\n\r\n if (updatedLineItem.metadata) {\r\n if (li.metadata1) {\r\n updatedLineItem.metadata.push({ name: lineItemRollup1, value: li.metadata1.trim() });\r\n }\r\n\r\n if (lineItemRollup2 && li.metadata2) {\r\n updatedLineItem.metadata.push({ name: lineItemRollup2, value: li.metadata2.trim() });\r\n }\r\n }\r\n\r\n return updatedLineItem;\r\n });\r\n\r\n return commands;\r\n }\r\n }, [\r\n isAddMode,\r\n lineItems,\r\n bidPackageId,\r\n alternateName,\r\n lineItemRollup2,\r\n lineItemRollup1,\r\n lineItemsToEdit,\r\n ]);\r\n\r\n const deleteLineItemButton = useCallback(\r\n (props: GridCellProps) => {\r\n return (\r\n \r\n {\r\n removeLineItem(props.dataItem);\r\n }}\r\n >\r\n \r\n \r\n \r\n );\r\n },\r\n [removeLineItem, t],\r\n );\r\n\r\n // ref to the grid container div\r\n // used as the element to anchor any droplist elements on\r\n const gridContainer = useRef(null);\r\n\r\n const descriptionTextInput = useCallback(\r\n (gcp: GridCellProps) => {\r\n const autoFocus = isAddMode;\r\n\r\n return (\r\n {\r\n // Add in the columnIndex / rowIndex to the event so we have that in the main paste handler code so we know where the\r\n // paste originated from\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const eventAsAny = e as any;\r\n\r\n eventAsAny.columnIndex = gcp.columnIndex;\r\n eventAsAny.rowIndex = gcp.dataIndex;\r\n }}\r\n />\r\n );\r\n },\r\n [isAddMode],\r\n );\r\n\r\n const quantityNumericInput = useCallback((gcp: GridCellProps) => {\r\n return (\r\n {\r\n // Add in the columnIndex / rowIndex to the event so we have that in the main paste handler code so we know where the\r\n // paste originated from\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const eventAsAny = e as any;\r\n\r\n eventAsAny.columnIndex = gcp.columnIndex;\r\n eventAsAny.rowIndex = gcp.dataIndex;\r\n }}\r\n />\r\n );\r\n }, []);\r\n\r\n const unitOfMeasureDropList = useCallback(\r\n (gcp: GridCellProps) => (\r\n {\r\n // Add in the columnIndex / rowIndex to the event so we have that in the main paste handler code so we know where the\r\n // paste originated from\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const eventAsAny = e as any;\r\n\r\n eventAsAny.columnIndex = gcp.columnIndex;\r\n eventAsAny.rowIndex = gcp.dataIndex;\r\n }}\r\n />\r\n ),\r\n [gridContainer, unitsOfMeasure],\r\n );\r\n\r\n const unitPriceNumericInput = useCallback(\r\n (gcp: GridCellProps) => (\r\n {\r\n // Add in the columnIndex / rowIndex to the event so we have that in the main paste handler code so we know where the\r\n // paste originated from\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const eventAsAny = e as any;\r\n\r\n eventAsAny.columnIndex = gcp.columnIndex;\r\n eventAsAny.rowIndex = gcp.dataIndex;\r\n }}\r\n />\r\n ),\r\n [],\r\n );\r\n\r\n const classificationLevel1DropList = useCallback(\r\n (gcp: GridCellProps) => (\r\n {\r\n // Add in the columnIndex / rowIndex to the event so we have that in the main paste handler code so we know where the\r\n // paste originated from\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const eventAsAny = e as any;\r\n\r\n eventAsAny.columnIndex = gcp.columnIndex;\r\n eventAsAny.rowIndex = gcp.dataIndex;\r\n }}\r\n />\r\n ),\r\n [gridContainer, level1Classifications, addNewLevel1Classification],\r\n );\r\n\r\n const classificationLevel2DropList = useCallback(\r\n (gcp: GridCellProps) => (\r\n {\r\n // Add in the columnIndex / rowIndex to the event so we have that in the main paste handler code so we know where the\r\n // paste originated from\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const eventAsAny = e as any;\r\n\r\n eventAsAny.columnIndex = gcp.columnIndex;\r\n eventAsAny.rowIndex = gcp.dataIndex;\r\n }}\r\n />\r\n ),\r\n [gridContainer, level2Classifications, addNewLevel2Classification],\r\n );\r\n\r\n const validateLineItems = useCallback(\r\n (lineItemsToValidate: LineItemInfo[]): boolean => {\r\n setErrors([]); // clear any previous errors\r\n\r\n let validationErrors: string[] = [];\r\n\r\n const descriptions = lineItemsToValidate.map((li) => li.description.trim());\r\n\r\n const missingDescription = descriptions.find((desc) => desc.length === 0);\r\n if (missingDescription) {\r\n validationErrors = validationErrors.concat(t('bid-package:lineItemDescriptionRequired'));\r\n }\r\n\r\n const missingUnit = lineItemsToValidate.find((li) => (li.unit ?? '').trim().length === 0);\r\n if (missingUnit) {\r\n validationErrors = validationErrors.concat(t('bid-package:lineItemUnitRequired'));\r\n }\r\n\r\n setErrors(validationErrors);\r\n\r\n return validationErrors.length === 0;\r\n },\r\n [t],\r\n );\r\n\r\n const validateAndSave = useCallback(() => {\r\n const success = validateLineItems(lineItems);\r\n if (success) {\r\n onSaveClick(getCommands());\r\n }\r\n }, [getCommands, lineItems, onSaveClick, validateLineItems]);\r\n\r\n // item changed handler - handles GridItemChangeEvent for any cell in the grid\r\n const itemChanged = useCallback(\r\n (e: GridItemChangeEvent) => {\r\n if (e.field) {\r\n const editedLineItems = lineItems.map((li) => {\r\n // update the changed field on the line item\r\n li = li.id === e.dataItem['id'] ? { ...li, [e.field ?? '']: e.value } : li;\r\n // if the metadata1 is empty, its metadata2 should be forced to be empty\r\n if ((li.metadata1 ?? '').trim().length === 0) {\r\n li.metadata2 = '';\r\n }\r\n li.changed = true;\r\n li.metadataChanged = e.field === 'metadata1' || e.field === 'metadata2';\r\n return li;\r\n });\r\n setLineItems(editedLineItems);\r\n if (errors.length > 0) {\r\n validateLineItems(editedLineItems);\r\n }\r\n }\r\n },\r\n [errors.length, lineItems, validateLineItems],\r\n );\r\n\r\n return useMemo(() => {\r\n return (\r\n
    \r\n

    {isAddMode ? t('bid-package:addLineItems') : t('bid-package:editLineItems')}

    \r\n {\r\n if (isAddMode && e.key.toUpperCase() === GeneralConstants.KEY_N && e.altKey) {\r\n addNewLineItem();\r\n }\r\n }}\r\n >\r\n \r\n {isAddMode ? (\r\n \r\n \r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n \r\n \r\n \r\n \r\n \r\n\r\n {lineItemRollup2 ? (\r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {isAddMode ? : <>}\r\n\r\n {/* NOTE: We only allow the user to paste things in 'add' mode */}\r\n {isAddMode ? (\r\n \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n\r\n
    {t('general:pasteClipboardDataToCreateLineItemsMessage')}
    \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n \r\n \r\n
    \r\n\r\n \r\n
    \r\n li.changed)}\r\n />\r\n {\r\n onDiscardClick(lineItems);\r\n }}\r\n />\r\n
    \r\n
    \r\n \r\n );\r\n }, [\r\n addNewLineItem,\r\n classificationLevel1DropList,\r\n classificationLevel2DropList,\r\n deleteLineItemButton,\r\n descriptionTextInput,\r\n errors,\r\n handlePaste,\r\n isAddMode,\r\n itemChanged,\r\n lineItemRollup2,\r\n lineItems,\r\n onDiscardClick,\r\n quantityNumericInput,\r\n t,\r\n unitOfMeasureDropList,\r\n unitPriceNumericInput,\r\n validateAndSave,\r\n ]);\r\n};\r\n\r\nexport default AddEditLineItemsForm;\r\n","import { IconProp } from '@fortawesome/fontawesome-svg-core';\r\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React from 'react';\r\nimport './KeyboardShortcutsInformation.scss';\r\n\r\nexport interface KeyboardShortcutsInformationProps {\r\n info: KeyboardShortcutsInformation_Info;\r\n}\r\n\r\nexport interface KeyboardShortcutsInformation_Info {\r\n title: string;\r\n groups: KeyboardShortcutsInformation_Group[];\r\n}\r\n\r\nexport interface KeyboardShortcutsInformation_Group {\r\n title: string;\r\n listings: KeyboardShortcutsInformation_Listing[];\r\n}\r\n\r\nexport interface KeyboardShortcutsInformation_Listing {\r\n keys: KeyboardShortcutsInformation_ListingKeyInfo[][]; // An array of arrays, to hold multiple sets of keys that trigger the same action\r\n title: string;\r\n circleColor?:\r\n | 'gray'\r\n | 'light-blue'\r\n | 'light-gray'\r\n | 'orange'\r\n | 'red'\r\n | 'yellow'\r\n | 'yellow-striped';\r\n}\r\n\r\nexport type KeyboardShortcutsInformation_ListingKeyInfo =\r\n | string\r\n | {\r\n key: IconProp;\r\n };\r\n\r\nconst KeyboardShortcutsInformation: React.FC = ({ info }) => {\r\n return (\r\n
    \r\n

    {info.title}

    \r\n\r\n
    \r\n {info.groups.map((currGroup, i) => {\r\n return (\r\n
    \r\n \r\n\r\n
    \r\n {currGroup.listings.map((currListing, currListingIndex) => {\r\n return (\r\n
    \r\n 0 ? ' mr-2' : 'mr-1'\r\n }`}\r\n >\r\n {currListing.keys.map((currKeyboardKeySet, currKeyboardKeySetIndex) => {\r\n return (\r\n \r\n {currKeyboardKeySetIndex > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n {currKeyboardKeySet.map((currKeyboardKey, currKeyboardKeyIndex) => {\r\n return (\r\n \r\n
    \r\n {typeof currKeyboardKey === 'object' ? (\r\n \r\n ) : (\r\n currKeyboardKey\r\n )}\r\n
    \r\n\r\n {currKeyboardKeyIndex < currKeyboardKeySet.length - 1 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n );\r\n })}\r\n
    \r\n );\r\n })}\r\n
    \r\n\r\n
    \r\n\r\n
    {currListing.title}
    \r\n\r\n {currListing.circleColor ? (\r\n
    \r\n ) : (\r\n <> \r\n )}\r\n
    \r\n );\r\n })}\r\n
    \r\n
    \r\n );\r\n })}\r\n \r\n \r\n );\r\n};\r\n\r\nexport default KeyboardShortcutsInformation;\r\n","import React, { useRef } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport KeyboardShortcutsInformation, {\r\n KeyboardShortcutsInformation_Info,\r\n} from '../../../../common-page-components/keyboard-shortcuts-info/KeyboardShortcutsInformation';\r\n\r\nconst BidPackageKeyboardShortcuts: React.FC = () => {\r\n const { t } = useTranslation();\r\n\r\n const keyboardShortcutsInfo = useRef({\r\n title: t('general:keyboardShortcuts'),\r\n groups: [\r\n {\r\n title: t('general:general'),\r\n listings: [\r\n {\r\n keys: [['Tab']],\r\n title: t('general:keyboardShortcuts_JumpToNextCell'),\r\n },\r\n {\r\n keys: [['Shift', 'Tab']],\r\n title: t('general:keyboardShortcuts_JumpToPreviousCell'),\r\n },\r\n {\r\n keys: [[{ key: 'arrow-up' }]],\r\n title: t('general:keyboardShortcuts_JumpToCellAbove'),\r\n },\r\n {\r\n keys: [[{ key: 'arrow-down' }], ['Enter']],\r\n title: t('general:keyboardShortcuts_JumpToCellBelow'),\r\n },\r\n ],\r\n },\r\n\r\n {\r\n title: t('bid-package:keyboardShortcuts_EnteringBids'),\r\n listings: [\r\n {\r\n keys: [['G']],\r\n title: t('bid-package:keyboardShortcuts_Classifications_G'),\r\n circleColor: 'orange',\r\n },\r\n {\r\n keys: [['I']],\r\n title: t('bid-package:keyboardShortcuts_Classifications_I'),\r\n },\r\n {\r\n keys: [['M']],\r\n title: t('bid-package:keyboardShortcuts_Classifications_M'),\r\n circleColor: 'light-blue',\r\n },\r\n {\r\n keys: [['O']],\r\n title: t('bid-package:keyboardShortcuts_Classifications_O'),\r\n circleColor: 'yellow',\r\n },\r\n {\r\n keys: [['R']],\r\n title: t('bid-package:keyboardShortcuts_Classifications_R'),\r\n circleColor: 'red',\r\n },\r\n {\r\n keys: [['S']],\r\n title: t('bid-package:keyboardShortcuts_Classifications_S'),\r\n circleColor: 'gray',\r\n },\r\n {\r\n keys: [['Space']],\r\n title: t('bid-package:keyboardShortcuts_Classifications_Space'),\r\n circleColor: 'light-gray',\r\n },\r\n {\r\n keys: [[]],\r\n title: t('bid-package:keyboardShortcuts_UnleveledBids'),\r\n circleColor: 'yellow-striped',\r\n },\r\n ],\r\n },\r\n\r\n {\r\n title: t('bid-package:keyboardShortcuts_AddEditBidders'),\r\n listings: [\r\n {\r\n keys: [['Alt', 'N']],\r\n title: t('bid-package:keyboardShortcuts_AddEditBidders_AddNewRow'),\r\n },\r\n {\r\n keys: [['Alt', 'S']],\r\n title: t('bid-package:keyboardShortcuts_SaveChanges'),\r\n },\r\n ],\r\n },\r\n\r\n {\r\n title: t('bid-package:keyboardShortcuts_AddEditLineItems'),\r\n listings: [\r\n {\r\n keys: [['Alt', 'N']],\r\n title: t('bid-package:keyboardShortcuts_AddEditLineItems_AddNewRow'),\r\n },\r\n {\r\n keys: [['Alt', 'S']],\r\n title: t('bid-package:keyboardShortcuts_SaveChanges'),\r\n },\r\n ],\r\n },\r\n ],\r\n });\r\n\r\n return (\r\n <>\r\n \r\n \r\n );\r\n};\r\n\r\nexport default BidPackageKeyboardShortcuts;\r\n","import React from 'react';\nimport { Alert } from 'reactstrap';\nimport { IconProp } from '@fortawesome/fontawesome-svg-core';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport './BTAlert.scss';\n\nexport type AlertType = 'warning' | 'error';\n\ninterface Props {\n type: AlertType;\n message: string;\n icon?: IconProp;\n}\n\nconst BTAlert: React.FC = (props) => {\n const color = typeToColorMap[props.type];\n\n return (\n
    \n \n {!props.icon ? (\n <>\n ) : (\n \n \n \n )}\n {props.message}\n \n
    \n );\n};\n\nconst typeToColorMap: Record = {\n warning: 'warning',\n error: 'danger',\n};\n\nexport default BTAlert;\n","import React, { useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { NotificationService } from '../../../services/notification/notification-service';\nimport BTAlert, { AlertType } from '../alert/BTAlert';\n\ninterface Props {\n liveUpdatesRegistrationFailed: boolean;\n}\n\nconst NotificationServiceStatusMessage: React.FC = (props) => {\n const { t } = useTranslation();\n\n const [alert, setAlert] = useState();\n const isNotificationServiceReconnecting = useRef(false);\n\n // Handle notification service reconnecting/reconnected/closed events\n useEffect(() => {\n NotificationService.onReconnecting(() => {\n isNotificationServiceReconnecting.current = true;\n setAlert({ type: 'warning', message: t('general:liveUpdatesReconnecting') });\n });\n\n NotificationService.onReconnected(() => {\n isNotificationServiceReconnecting.current = false;\n setAlert(undefined);\n });\n\n NotificationService.onClose(() => {\n if (isNotificationServiceReconnecting.current) {\n isNotificationServiceReconnecting.current = false;\n setAlert({ type: 'error', message: t('general:liveUpdatesConnectFailed') });\n }\n });\n\n return () => {\n NotificationService.offReconnecting();\n NotificationService.offReconnected();\n NotificationService.offClose();\n };\n }, [t]);\n\n const alertToUse: Alert | undefined = props.liveUpdatesRegistrationFailed\n ? { type: 'error', message: t('general:liveUpdatesConnectFailed') }\n : alert;\n\n return !alertToUse ? (\n <>\n ) : (\n \n );\n};\n\ninterface Alert {\n type: AlertType;\n message: string;\n}\n\nexport default NotificationServiceStatusMessage;\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport moment from 'moment';\r\nimport React, { useContext, useEffect, useMemo, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Link } from 'react-router-dom';\r\nimport { Subscription } from 'rxjs';\r\nimport { Project } from '../../../../../classes/odata/project';\r\nimport ApplicationRoutes from '../../../../../constants/routes';\r\nimport { isEnvironment } from '../../../../../utils/general';\r\nimport BTIconButtonToggle from '../../../../common-page-components/controls/icon-button-toggle/BTIconButtonToggle';\r\nimport { FormDropDownListOption } from '../../../../common-page-components/forms/FormDropDownList';\r\nimport { BTGeneralContext } from '../../../../common-page-components/general-contexts/BTGeneralContext';\r\nimport BTDropDownList from '../../../../common-page-components/inputs/BTDropDownList';\r\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport NotificationServiceStatusMessage from '../../../../common-page-components/notification-service-status-message/NotificationServiceStatusMessage';\r\nimport SvgImage from '../../../../common-page-components/svg-image/SvgImage';\r\nimport useBidPackagePageContext from '../BidPackagePageContext';\r\nimport { ProjectApi } from '../../../../../services';\r\n\r\ninterface Props {\r\n allBidPackageDropdownOptions: FormDropDownListOption[];\r\n anyEntitiesAreFrozen: boolean;\r\n bidPackageNotes: string | null;\r\n bidPackageTooltip: string;\r\n canLockBidPackage: boolean;\r\n isGeneralCondition: boolean;\r\n liveUpdateRegistrationFailed: boolean;\r\n lockedByUserEmail: string;\r\n onSelectedBidPackageChange: (newValue: unknown) => void;\r\n projectInfo: Project;\r\n selectedBidPackageId: string | null;\r\n}\r\n\r\nconst BidPackagePageHeader: React.FC = ({\r\n allBidPackageDropdownOptions,\r\n anyEntitiesAreFrozen,\r\n bidPackageNotes,\r\n bidPackageTooltip,\r\n canLockBidPackage,\r\n isGeneralCondition,\r\n liveUpdateRegistrationFailed,\r\n lockedByUserEmail,\r\n onSelectedBidPackageChange,\r\n projectInfo,\r\n selectedBidPackageId,\r\n}) => {\r\n const { t } = useTranslation();\r\n\r\n const { pageScroll_Y$ } = useContext(BTGeneralContext);\r\n\r\n const [pageIsScrolled_Y, setPageIsScrolled_Y] = useState(false);\r\n const [projectImageBlobUrl, setProjectImageBlobUrl] = useState();\r\n const currentProjectImageUri = useRef();\r\n\r\n const { showInfoNotification, showErrorNotification } = useContext(NotificationPanelContext);\r\n\r\n const {\r\n bidPackageNotes_Open,\r\n keyboardShortcutsInfoIsOpen_Change,\r\n lockBidPackage_Change,\r\n viewProjectInfo_Open,\r\n } = useBidPackagePageContext();\r\n\r\n useEffect(() => {\r\n const getProjectImageUrl = async () => {\r\n if (currentProjectImageUri.current !== projectInfo.imageUri) {\r\n if (projectInfo.imageUri) {\r\n // Fetch the latest project image if there is one\r\n try {\r\n const imageBlobUrl = await ProjectApi.getProjectImageBlobUrl(\r\n projectInfo.id!,\r\n projectInfo.imageUri,\r\n );\r\n\r\n setProjectImageBlobUrl(imageBlobUrl);\r\n } catch (error) {\r\n showErrorNotification(t('general:error'), t('project:projectImageLoadError'));\r\n }\r\n } else {\r\n // Clear the blob url because the project image may be removed or never set\r\n setProjectImageBlobUrl(null);\r\n }\r\n\r\n currentProjectImageUri.current = projectInfo.imageUri;\r\n }\r\n };\r\n\r\n getProjectImageUrl();\r\n }, [projectImageBlobUrl, projectInfo.id, projectInfo.imageUri, showErrorNotification, t]);\r\n\r\n // Listen for other events\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n pageScroll_Y$.subscribe((offset) => {\r\n setPageIsScrolled_Y(offset >= 25);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [pageScroll_Y$]);\r\n\r\n return useMemo(() => {\r\n return (\r\n
    \r\n
    \r\n \r\n\r\n
    \r\n
    \r\n
    \r\n {projectImageBlobUrl ? (\r\n
    \r\n \"Project\"\r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n
    \r\n \r\n \r\n {projectInfo.name}\r\n \r\n \r\n\r\n
    \r\n {!isEnvironment('prod') ? (\r\n {\r\n await navigator.clipboard.writeText(projectInfo.name!);\r\n\r\n showInfoNotification(\r\n t('general:copied'),\r\n t('bid-package:projectNameCopiedToClipboard'),\r\n );\r\n }}\r\n />\r\n ) : (\r\n <>\r\n )}\r\n\r\n {\r\n viewProjectInfo_Open();\r\n }}\r\n />\r\n\r\n {\r\n keyboardShortcutsInfoIsOpen_Change(true);\r\n }}\r\n data-testid=\"BidPackagePage_ViewKeyboardShortcutsIcon\"\r\n />\r\n
    \r\n
    \r\n\r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n {allBidPackageDropdownOptions ? (\r\n
    \r\n v.value === selectedBidPackageId)\r\n ?.value\r\n }\r\n onChangeHandler={onSelectedBidPackageChange}\r\n >\r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n {/* Show a snowflake icon when not in prod, to help QA debug when things got frozen during a test\r\n but they can't see the banner in the screenshot */}\r\n {!isEnvironment('prod') && anyEntitiesAreFrozen ? (\r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n \r\n\r\n {\r\n bidPackageNotes_Open(bidPackageNotes || '');\r\n }}\r\n value={!!bidPackageNotes}\r\n data-testid=\"bidPackageNotesButton\"\r\n />\r\n\r\n {/* TODO - when this gets wired up, confirm this button isn't needed for general condition bid packages */}\r\n {isGeneralCondition ? (\r\n <>\r\n ) : (\r\n <>\r\n // TODO - this button will be wired up later\r\n\r\n // {\r\n // // return;\r\n // }}\r\n // value={false}\r\n // />\r\n )}\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n );\r\n }, [\r\n allBidPackageDropdownOptions,\r\n anyEntitiesAreFrozen,\r\n bidPackageNotes,\r\n bidPackageNotes_Open,\r\n bidPackageTooltip,\r\n canLockBidPackage,\r\n isGeneralCondition,\r\n keyboardShortcutsInfoIsOpen_Change,\r\n liveUpdateRegistrationFailed,\r\n lockBidPackage_Change,\r\n lockedByUserEmail,\r\n onSelectedBidPackageChange,\r\n pageIsScrolled_Y,\r\n projectImageBlobUrl,\r\n projectInfo.bidDueDate,\r\n projectInfo.id,\r\n projectInfo.name,\r\n selectedBidPackageId,\r\n showInfoNotification,\r\n t,\r\n viewProjectInfo_Open,\r\n ]);\r\n};\r\n\r\nexport default BidPackagePageHeader;\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class DeleteAdjustmentOnBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public companyName: string,\r\n public alternateName: string | null,\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.DeleteAdjustmentOnBidPackage',\r\n 'bid-package/delete-adjustment',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class SetAdjustmentOnBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public companyName: string,\r\n public alternateName: string | null,\r\n public value: number | null,\r\n public newBidAmount: number | null,\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.SetAdjustmentOnBidPackage',\r\n 'bid-package/set-adjustment',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { clone } from 'lodash';\r\nimport { DeleteAdjustmentOnBidPackageCommand } from '../../../../../../classes/commands/bid-packages/delete-adjustment-on-bid-package-command';\r\nimport { SetAdjustmentOnBidPackageCommand } from '../../../../../../classes/commands/bid-packages/set-adjustment-on-bid-package-command';\r\nimport { Adjustment } from '../../../../../../classes/odata/adjustment';\r\nimport { Alternate } from '../../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { normalizeNullOrUndefined } from '../../../../../../utils/general';\r\nimport { areTrimmedStringsEqual } from '../../../../../../utils/strings';\r\nimport { generateUuid } from '../../../../../../utils/uuid';\r\n\r\ninterface ReturnValue {\r\n onChangeCallback_Adjustment: (\r\n currentBidPackage: BidPackage,\r\n bidValue: AdjustmentBidValue,\r\n ) => BidPackage;\r\n\r\n onBlurCallback_Adjustment: (\r\n originalBidPackage: BidPackage,\r\n currentBidPackage: BidPackage,\r\n projectAlternates: Alternate[],\r\n bidValue: AdjustmentBidValue,\r\n ) => ICommand | null;\r\n\r\n // Updates the bid package copy with the new data from the current bid package\r\n successFunction_Adjustment: (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n\r\n // Updates the current bid package with the data from the bid package copy\r\n errorFunction_Adjustment: (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n}\r\n\r\nconst useBidPackageBidHandler_Adjustments = (): ReturnValue => {\r\n return {\r\n onChangeCallback_Adjustment,\r\n onBlurCallback_Adjustment,\r\n successFunction_Adjustment,\r\n errorFunction_Adjustment,\r\n };\r\n};\r\n\r\nconst onChangeCallback_Adjustment = (\r\n currentBidPackage: BidPackage,\r\n bidValue: AdjustmentBidValue,\r\n): BidPackage => {\r\n const bidPackageCopy = clone(currentBidPackage);\r\n\r\n // NOTE: We allow negative values for adjustments\r\n\r\n const existingAdjustment = bidPackageCopy.getAdjustment(\r\n bidValue.alternateId || null,\r\n bidValue.bidderId,\r\n );\r\n\r\n if (existingAdjustment) {\r\n bidPackageCopy.setAdjustment(\r\n new Adjustment({\r\n ...existingAdjustment,\r\n value: bidValue.value,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n }),\r\n false,\r\n );\r\n } else if (bidValue.value !== undefined) {\r\n bidPackageCopy.setAdjustment(\r\n new Adjustment({\r\n id: generateUuid(),\r\n alternateId: bidValue.alternateId,\r\n bidPackageId: bidPackageCopy.id,\r\n bidderId: bidValue.bidderId,\r\n value: bidValue.value,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n }),\r\n false,\r\n );\r\n }\r\n\r\n return bidPackageCopy;\r\n};\r\n\r\nconst onBlurCallback_Adjustment = (\r\n originalBidPackage: BidPackage,\r\n currentBidPackage: BidPackage,\r\n projectAlternates: Alternate[],\r\n bidValue: AdjustmentBidValue,\r\n): ICommand | null => {\r\n // NOTE: We allow negative values for adjustments\r\n const alternateName =\r\n projectAlternates.find(\r\n (v) =>\r\n normalizeNullOrUndefined(v.id) ===\r\n normalizeNullOrUndefined(bidValue.alternateId),\r\n )?.name || null;\r\n\r\n const bidderCompanyName = currentBidPackage.getBidder(bidValue.bidderId)?.companyName || '';\r\n\r\n // NOTE: We get the original adjustment from the copy of the selected bid package so we can compare the values\r\n const existingAdjustment = originalBidPackage.getAdjustment(\r\n bidValue.alternateId || null,\r\n bidValue.bidderId,\r\n );\r\n\r\n let shouldSetAdjustment = false;\r\n\r\n if (existingAdjustment) {\r\n if (\r\n normalizeNullOrUndefined(existingAdjustment.value) !==\r\n normalizeNullOrUndefined(bidValue.value)\r\n ) {\r\n shouldSetAdjustment = true;\r\n }\r\n } else {\r\n shouldSetAdjustment = true;\r\n }\r\n\r\n let commandToProcess: ICommand | null = null;\r\n\r\n if (shouldSetAdjustment) {\r\n commandToProcess = new SetAdjustmentOnBidPackageCommand(\r\n currentBidPackage.id,\r\n bidderCompanyName,\r\n alternateName,\r\n bidValue.value as number,\r\n null,\r\n );\r\n }\r\n\r\n return commandToProcess;\r\n};\r\n\r\n// Updates data on a bid package\r\nconst successFunction_Adjustment = (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n // Delete the adjustment in the bid package copy\r\n if (command instanceof DeleteAdjustmentOnBidPackageCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n const alternate = alternates.find((v) =>\r\n areTrimmedStringsEqual(v.name || '', command.alternateName),\r\n );\r\n\r\n if (bidder) {\r\n copy.deleteAdjustment(alternate?.id || null, bidder.id || '');\r\n }\r\n\r\n return copy;\r\n }\r\n // Add or update the adjustment\r\n else if (command instanceof SetAdjustmentOnBidPackageCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n const alternate = alternates.find((v) =>\r\n areTrimmedStringsEqual(v.name || '', command.alternateName),\r\n );\r\n\r\n if (bidder) {\r\n const adjustmentToAddOrUpdate = clone(\r\n bidPackageWithUpdatedData.getAdjustment(alternate?.id || null, bidder.id || ''),\r\n );\r\n\r\n if (adjustmentToAddOrUpdate) {\r\n copy.setAdjustment(adjustmentToAddOrUpdate, false);\r\n }\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\n// Restores data on a bid package\r\nconst errorFunction_Adjustment = (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n // Restore the adjustment in the bid package or delete it if it was new\r\n if (\r\n command instanceof DeleteAdjustmentOnBidPackageCommand ||\r\n command instanceof SetAdjustmentOnBidPackageCommand\r\n ) {\r\n const copy = clone(bidPackageToUpdate);\r\n\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n const alternate = alternates.find((v) =>\r\n areTrimmedStringsEqual(v.name || '', command.alternateName),\r\n );\r\n\r\n const adjustmentToRestore = clone(\r\n bidPackageWithUpdatedData.getAdjustment(alternate?.id || null, bidder?.id || ''),\r\n );\r\n\r\n if (adjustmentToRestore) {\r\n copy.setAdjustment(adjustmentToRestore, false);\r\n } else {\r\n copy.deleteAdjustment(alternate?.id || null, bidder?.id || '');\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\nexport default useBidPackageBidHandler_Adjustments;\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class SetLineItemBidOnBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public lineItemId: string,\r\n public companyName: string,\r\n public price: number,\r\n public classification: number,\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.SetLineItemBidOnBidPackage',\r\n 'bid-package/set-line-item-bid',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { clone } from 'lodash';\r\nimport { DeleteLineItemBidOnBidPackageCommand } from '../../../../../../classes/commands/bid-packages/delete-line-item-bid-on-bid-package-command';\r\nimport { SetLineItemBidOnBidPackageCommand } from '../../../../../../classes/commands/bid-packages/set-line-item-bid-on-bid-package-command';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { BidPackageLineItemBid } from '../../../../../../classes/odata/bid-package-line-item-bid';\r\nimport { normalizeNullOrUndefined } from '../../../../../../utils/general';\r\nimport { generateUuid } from '../../../../../../utils/uuid';\r\nimport { BidClassificationTypes } from '../../../../../enums/bid-package-enums';\r\n\r\ninterface ReturnValue {\r\n onChangeCallback_LineItemBid: (\r\n currentBidPackage: BidPackage,\r\n bidValue: LineItemBidValue,\r\n ) => BidPackage;\r\n\r\n onBlurCallback_LineItemBid: (\r\n bidPackageCopy: BidPackage,\r\n currentBidPackage: BidPackage,\r\n bidValue: LineItemBidValue,\r\n ) => ICommand | null;\r\n\r\n // Updates the bid package copy with the new data from the current bid package\r\n successFunction_LineItemBid: (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n\r\n // Updates the current bid package with the data from the bid package copy\r\n errorFunction_LineItemBid: (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n}\r\n\r\nconst useBidPackageBidHandler_LineItemBids = (): ReturnValue => {\r\n return {\r\n onChangeCallback_LineItemBid,\r\n onBlurCallback_LineItemBid,\r\n successFunction_LineItemBid,\r\n errorFunction_LineItemBid,\r\n };\r\n};\r\n\r\nconst onChangeCallback_LineItemBid = (\r\n currentBidPackage: BidPackage,\r\n bidValue: LineItemBidValue,\r\n): BidPackage => {\r\n const bidPackageCopy = clone(currentBidPackage);\r\n\r\n const existingBid = bidPackageCopy.getLineItemBid(\r\n bidValue.bidPackageLineItemId!,\r\n bidValue.bidderId!,\r\n );\r\n\r\n if (existingBid) {\r\n const updatedBid = new BidPackageLineItemBid({\r\n ...existingBid,\r\n price: bidValue.price,\r\n classification: bidValue.classification || BidClassificationTypes.Unallocated,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n });\r\n\r\n bidPackageCopy.setLineItemBid(bidValue.bidPackageLineItemId!, updatedBid);\r\n }\r\n\r\n // If the bid isn't made up of all default values, add it\r\n else if (\r\n !(\r\n bidValue.classification === BidClassificationTypes.Unallocated &&\r\n bidValue.price === undefined &&\r\n bidValue.value === undefined\r\n )\r\n ) {\r\n bidPackageCopy.setLineItemBid(\r\n bidValue.bidPackageLineItemId!,\r\n new BidPackageLineItemBid({\r\n id: generateUuid(),\r\n bidPackageLineItemId: bidValue.bidPackageLineItemId,\r\n bidderId: bidValue.bidderId,\r\n price: bidValue.price,\r\n classification: bidValue.classification || BidClassificationTypes.Unallocated,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n }),\r\n );\r\n }\r\n\r\n return bidPackageCopy;\r\n};\r\n\r\nconst onBlurCallback_LineItemBid = (\r\n bidPackageCopy: BidPackage,\r\n currentBidPackage: BidPackage,\r\n bidValue: LineItemBidValue,\r\n): ICommand | null => {\r\n const matchingBidder = currentBidPackage.getBidder(bidValue.bidderId!);\r\n\r\n const matchingOriginalBid = bidPackageCopy.getLineItemBid(\r\n bidValue.bidPackageLineItemId!,\r\n bidValue.bidderId!,\r\n );\r\n\r\n const bidValueIsValid = BidPackageLineItemBid.isBidValid(bidValue.price, bidValue.classification);\r\n\r\n let commandToProcess: ICommand | null = null;\r\n\r\n let shouldAddOrUpdateBid = false;\r\n\r\n // If the bid already exists, check if it changed or should be deleted\r\n if (matchingOriginalBid) {\r\n // NOTE: We store partially entered bids as the user enters things, so we only want to generate a delete command\r\n // if the original bid was valid\r\n const originalBidValueIsValid = BidPackageLineItemBid.isBidValid(\r\n matchingOriginalBid.price,\r\n matchingOriginalBid.classification,\r\n );\r\n\r\n // If the price is not populated (regardless of the classification), we want to delete the bid\r\n if (originalBidValueIsValid && !bidValueIsValid) {\r\n commandToProcess = new DeleteLineItemBidOnBidPackageCommand(\r\n currentBidPackage.id,\r\n bidValue.bidPackageLineItemId!,\r\n matchingBidder!.companyName as string,\r\n );\r\n }\r\n // If the bid changed, update it\r\n else if (\r\n bidValueIsValid &&\r\n (normalizeNullOrUndefined(matchingOriginalBid.price) !==\r\n normalizeNullOrUndefined(bidValue.price) ||\r\n matchingOriginalBid.classification !== bidValue.classification)\r\n ) {\r\n shouldAddOrUpdateBid = true;\r\n }\r\n } else {\r\n if (bidValueIsValid) {\r\n // If the bid was new, add it\r\n shouldAddOrUpdateBid = true;\r\n }\r\n }\r\n\r\n if (shouldAddOrUpdateBid) {\r\n commandToProcess = new SetLineItemBidOnBidPackageCommand(\r\n currentBidPackage.id,\r\n bidValue.bidPackageLineItemId!,\r\n matchingBidder!.companyName as string,\r\n bidValue.price!,\r\n bidValue.classification!,\r\n );\r\n }\r\n\r\n return commandToProcess;\r\n};\r\n\r\n// Updates data on a bid package\r\nconst successFunction_LineItemBid = (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n // Delete the line item bid in the bid package copy\r\n if (command instanceof DeleteLineItemBidOnBidPackageCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n\r\n if (bidder) {\r\n copy.deleteLineItemBid(command.lineItemId, bidder.id || '');\r\n }\r\n\r\n return copy;\r\n }\r\n // Add or update the line item bid\r\n else if (command instanceof SetLineItemBidOnBidPackageCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n\r\n if (bidder) {\r\n const bidToAddOrUpdate = clone(\r\n bidPackageWithUpdatedData.getLineItemBid(command.lineItemId, bidder.id || ''),\r\n );\r\n\r\n if (bidToAddOrUpdate) {\r\n copy.setLineItemBid(command.lineItemId, bidToAddOrUpdate);\r\n }\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\n// Restores data on a bid package\r\nconst errorFunction_LineItemBid = (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n // Restore the line item bid in the bid package or delete it if it was new\r\n if (\r\n command instanceof DeleteLineItemBidOnBidPackageCommand ||\r\n command instanceof SetLineItemBidOnBidPackageCommand\r\n ) {\r\n const copy = clone(bidPackageToUpdate);\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n const bidToRestore = clone(\r\n bidPackageWithUpdatedData.getLineItemBid(command.lineItemId, bidder?.id || ''),\r\n );\r\n\r\n if (bidToRestore) {\r\n copy.setLineItemBid(command.lineItemId, bidToRestore);\r\n } else {\r\n copy.deleteLineItemBid(command.lineItemId, bidder?.id || '');\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\nexport default useBidPackageBidHandler_LineItemBids;\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class DeleteLineItemRollupBidOnBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public companyName: string,\r\n public alternateName: string | null,\r\n public metadataValues: string[],\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.DeleteLineItemRollupBidOnBidPackage',\r\n 'bid-package/delete-line-item-rollup-bid',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class SetLineItemRollupBidOnBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public companyName: string,\r\n public alternateName: string | null,\r\n public metadataValues: string[],\r\n public price: number,\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.SetLineItemRollupBidOnBidPackage',\r\n 'bid-package/set-line-item-rollup-bid',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { clone } from 'lodash';\r\nimport { DeleteLineItemRollupBidOnBidPackageCommand } from '../../../../../../classes/commands/bid-packages/delete-line-item-rollup-bid-on-bid-package-command';\r\nimport { SetLineItemRollupBidOnBidPackageCommand } from '../../../../../../classes/commands/bid-packages/set-line-item-rollup-bid-on-bid-package-command';\r\nimport { Alternate } from '../../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { BidPackageLineItemRollupBid } from '../../../../../../classes/odata/bid-package-line-item-rollup-bid';\r\nimport { normalizeNullOrUndefined } from '../../../../../../utils/general';\r\nimport { areTrimmedStringsEqual } from '../../../../../../utils/strings';\r\nimport { generateUuid } from '../../../../../../utils/uuid';\r\n\r\ninterface ReturnValue {\r\n onChangeCallback_LineItemRollupBid: (\r\n currentBidPackage: BidPackage,\r\n bidValue: LineItemRollupBidValue,\r\n ) => BidPackage;\r\n\r\n onBlurCallback_LineItemRollupBid: (\r\n originalBidPackage: BidPackage,\r\n currentBidPackage: BidPackage,\r\n projectAlternates: Alternate[],\r\n bidValue: LineItemRollupBidValue,\r\n ) => ICommand | null;\r\n\r\n // Updates the bid package copy with the new data from the current bid package\r\n successFunction_LineItemRollupBid: (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n\r\n // Updates the current bid package with the data from the bid package copy\r\n errorFunction_LineItemRollupBid: (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n}\r\n\r\nconst useBidPackageBidHandler_LineItemRollupBids = (): ReturnValue => {\r\n return {\r\n onChangeCallback_LineItemRollupBid,\r\n onBlurCallback_LineItemRollupBid,\r\n successFunction_LineItemRollupBid,\r\n errorFunction_LineItemRollupBid,\r\n };\r\n};\r\n\r\nconst onChangeCallback_LineItemRollupBid = (\r\n currentBidPackage: BidPackage,\r\n bidValue: LineItemRollupBidValue,\r\n): BidPackage => {\r\n const bidPackageCopy = clone(currentBidPackage);\r\n\r\n const existingRollupBid = bidPackageCopy.getLineItemRollupBid(\r\n bidValue.alternateId || null,\r\n bidValue.bidderId!,\r\n bidValue.lineItemRollup1,\r\n bidValue.lineItemRollup2,\r\n );\r\n\r\n if (existingRollupBid) {\r\n const updatedBid = new BidPackageLineItemRollupBid({\r\n ...existingRollupBid,\r\n bidValue: bidValue.price,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n });\r\n\r\n bidPackageCopy.setLineItemRollupBid(updatedBid);\r\n } else if (!(bidValue.price === undefined && bidValue.value === undefined)) {\r\n bidPackageCopy.setLineItemRollupBid(\r\n new BidPackageLineItemRollupBid({\r\n id: generateUuid(),\r\n bidderId: bidValue.bidderId,\r\n bidValue: bidValue.price,\r\n alternateId: bidValue.alternateId,\r\n metadataValue1: bidValue.lineItemRollup1 || undefined,\r\n metadataValue2: bidValue.lineItemRollup2 || undefined,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n }),\r\n );\r\n }\r\n\r\n return bidPackageCopy;\r\n};\r\n\r\nconst onBlurCallback_LineItemRollupBid = (\r\n originalBidPackage: BidPackage,\r\n currentBidPackage: BidPackage,\r\n projectAlternates: Alternate[],\r\n bidValue: LineItemRollupBidValue,\r\n): ICommand | null => {\r\n const bidValueIsValid = bidValue.price !== undefined && typeof bidValue.price === 'number';\r\n\r\n const matchingBidder = currentBidPackage.getBidder(bidValue.bidderId);\r\n\r\n const matchingAlternate = projectAlternates.find((v) => v.id === bidValue.alternateId);\r\n\r\n const matchingOriginalBid = originalBidPackage.getLineItemRollupBid(\r\n bidValue.alternateId || null,\r\n bidValue.bidderId,\r\n bidValue.lineItemRollup1,\r\n bidValue.lineItemRollup2,\r\n );\r\n\r\n let commandToProcess: ICommand | null = null;\r\n\r\n let shouldAddOrUpdateBid = false;\r\n\r\n // If the bid already exists, check if it changed or should be deleted\r\n if (matchingOriginalBid) {\r\n // If the price is not populated, we want to delete the bid\r\n if (!bidValueIsValid) {\r\n commandToProcess = new DeleteLineItemRollupBidOnBidPackageCommand(\r\n currentBidPackage.id,\r\n matchingBidder!.companyName as string,\r\n matchingAlternate?.name || null,\r\n [bidValue.lineItemRollup1 || '', bidValue.lineItemRollup2 || ''].filter((v) => v),\r\n );\r\n }\r\n // If the bid changed, update it\r\n else if (\r\n normalizeNullOrUndefined(matchingOriginalBid.bidValue) !==\r\n normalizeNullOrUndefined(bidValue.price)\r\n ) {\r\n shouldAddOrUpdateBid = true;\r\n }\r\n } else {\r\n if (bidValueIsValid) {\r\n // If the bid was new, add it\r\n shouldAddOrUpdateBid = true;\r\n }\r\n }\r\n\r\n if (shouldAddOrUpdateBid) {\r\n commandToProcess = new SetLineItemRollupBidOnBidPackageCommand(\r\n currentBidPackage.id,\r\n matchingBidder!.companyName as string,\r\n matchingAlternate?.name || null,\r\n [bidValue.lineItemRollup1 || '', bidValue.lineItemRollup2 || ''].filter((v) => v),\r\n bidValue.price as number,\r\n );\r\n }\r\n\r\n return commandToProcess;\r\n};\r\n\r\n// Updates data on a bid package\r\nconst successFunction_LineItemRollupBid = (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n // Delete the line item rollup bid in the bid package copy\r\n if (command instanceof DeleteLineItemRollupBidOnBidPackageCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n const alternate = alternates.find((v) =>\r\n areTrimmedStringsEqual(v.name || '', command.alternateName),\r\n );\r\n\r\n if (bidder) {\r\n copy.deleteLineItemRollupBid(\r\n alternate?.id || null,\r\n bidder.id || '',\r\n command.metadataValues[0] || null,\r\n command.metadataValues[1] || null,\r\n );\r\n }\r\n\r\n return copy;\r\n }\r\n // Add or update the line item bid\r\n else if (command instanceof SetLineItemRollupBidOnBidPackageCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n const alternate = alternates.find((v) =>\r\n areTrimmedStringsEqual(v.name || '', command.alternateName),\r\n );\r\n\r\n const bidToAddOrUpdate = clone(\r\n bidPackageWithUpdatedData.getLineItemRollupBid(\r\n alternate?.id || null,\r\n bidder?.id || '',\r\n command.metadataValues[0] || null,\r\n command.metadataValues[1] || null,\r\n ),\r\n );\r\n\r\n if (bidToAddOrUpdate) {\r\n copy.setLineItemRollupBid(bidToAddOrUpdate);\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\n// Restores data on a bid package\r\nconst errorFunction_LineItemRollupBid = (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n // Restore the line item bid in the bid package or delete it if it was new\r\n if (\r\n command instanceof DeleteLineItemRollupBidOnBidPackageCommand ||\r\n command instanceof SetLineItemRollupBidOnBidPackageCommand\r\n ) {\r\n const copy = clone(bidPackageToUpdate);\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n\r\n if (bidder) {\r\n const alternate = alternates.find((v) =>\r\n areTrimmedStringsEqual(v.name || '', command.alternateName),\r\n );\r\n\r\n const bidToRestore = clone(\r\n bidPackageWithUpdatedData.getLineItemRollupBid(\r\n alternate?.id || null,\r\n bidder?.id || '',\r\n command.metadataValues[0] || null,\r\n command.metadataValues[1] || null,\r\n ),\r\n );\r\n\r\n if (bidToRestore) {\r\n copy.setLineItemRollupBid(bidToRestore);\r\n } else {\r\n copy.deleteLineItemRollupBid(\r\n alternate?.id || null,\r\n bidder?.id || '',\r\n command.metadataValues[0] || null,\r\n command.metadataValues[1] || null,\r\n );\r\n }\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\nexport default useBidPackageBidHandler_LineItemRollupBids;\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class SetBidderRequirementFulfillmentOnBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public description: string,\r\n public isTradeRequirement: boolean,\r\n public companyName: string,\r\n public requirementFulfillmentType: number,\r\n public price: number | null,\r\n public classification: number | null,\r\n public value: string | null,\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.SetBidderRequirementFulfillmentOnBidPackage',\r\n 'bid-package/set-bidder-requirement-fulfillment',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { clone } from 'lodash';\r\nimport { DeleteBidderRequirementFulfillmentOnBidPackageCommand } from '../../../../../../classes/commands/bid-packages/delete-bidder-requirement-fulfillment-on-bid-package-command';\r\nimport { SetBidderRequirementFulfillmentOnBidPackageCommand } from '../../../../../../classes/commands/bid-packages/set-bidder-requirement-fulfillment-on-bid-package-command';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { BidPackageRequirementFulfillment } from '../../../../../../classes/odata/bid-package-requirement-fulfillment';\r\nimport { Bidder } from '../../../../../../classes/odata/bidder';\r\nimport EntityValidationConstants from '../../../../../../constants/general/entity-validation-constants';\r\nimport { normalizeNullOrUndefined } from '../../../../../../utils/general';\r\nimport { generateUuid } from '../../../../../../utils/uuid';\r\nimport {\r\n BidClassificationTypes,\r\n RequirementFulfillmentTypes,\r\n} from '../../../../../enums/bid-package-enums';\r\n\r\ninterface ReturnValue {\r\n onChangeCallback_RequirementFulfillment: (\r\n currentBidPackage: BidPackage,\r\n bidValue: RequirementFulfillmentBidValue,\r\n ) => BidPackage;\r\n\r\n onBlurCallback_RequirementFulfillment: (\r\n originalBidPackage: BidPackage,\r\n currentBidPackage: BidPackage,\r\n bidValue: RequirementFulfillmentBidValue,\r\n ) => ICommand | null;\r\n\r\n // Updates the bid package copy with the new data from the current bid package\r\n successFunction_RequirementFulfillment: (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n\r\n // Updates the current bid package with the data from the bid package copy\r\n errorFunction_RequirementFulfillment: (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n}\r\n\r\nconst useBidPackageBidHandler_RequirementFulfillments = (): ReturnValue => {\r\n return {\r\n onChangeCallback_RequirementFulfillment,\r\n onBlurCallback_RequirementFulfillment,\r\n successFunction_RequirementFulfillment,\r\n errorFunction_RequirementFulfillment,\r\n };\r\n};\r\n\r\nconst onChangeCallback_RequirementFulfillment = (\r\n currentBidPackage: BidPackage,\r\n bidValue: RequirementFulfillmentBidValue,\r\n): BidPackage => {\r\n const bidPackageCopy = clone(currentBidPackage);\r\n\r\n const existingRequirement = bidPackageCopy.getRequirement(bidValue.requirementId || '');\r\n if (existingRequirement) {\r\n let price: number | undefined = undefined;\r\n let classification: BidClassificationTypes | undefined = undefined;\r\n let value: string | undefined = undefined;\r\n\r\n // NOTE: We do not set a value for qualitative requirement fulfillments, its existence is its value\r\n switch (existingRequirement.requirementFulfillmentType) {\r\n case RequirementFulfillmentTypes.Quantitative:\r\n price = bidValue.price;\r\n classification = bidValue.classification || BidClassificationTypes.Unallocated;\r\n break;\r\n\r\n case RequirementFulfillmentTypes.Freeform:\r\n value = (bidValue.value as string) || '' || undefined;\r\n if (\r\n value &&\r\n value.length >\r\n EntityValidationConstants.RequirementFulfillmentEntityLimits.Value_MaxLength\r\n ) {\r\n value = value.slice(\r\n 0,\r\n EntityValidationConstants.RequirementFulfillmentEntityLimits.Value_MaxLength,\r\n );\r\n }\r\n\r\n break;\r\n }\r\n\r\n const existingFulfillment = bidPackageCopy.getRequirementFulfillment(\r\n bidValue.requirementId || '',\r\n bidValue.bidderId || '',\r\n );\r\n\r\n if (existingFulfillment) {\r\n // For qualitative requirements (just a checkbox), we want to remove them from the array if the value was false.\r\n // NOTE: This does not affect the isDirty flag, as we fire the change / blur events for qualitative fulfillment\r\n // value changes without relying on an explicit blur action by the user.\r\n if (\r\n existingRequirement.requirementFulfillmentType ===\r\n RequirementFulfillmentTypes.Qualitative &&\r\n !bidValue.value\r\n ) {\r\n bidPackageCopy.deleteRequirementFulfillment(\r\n bidValue.requirementId || '',\r\n bidValue.bidderId || '',\r\n );\r\n } else {\r\n bidPackageCopy.setRequirementFulfillment(\r\n bidValue.requirementId || '',\r\n new BidPackageRequirementFulfillment({\r\n ...existingFulfillment,\r\n price: price,\r\n classification: classification,\r\n value: value,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n }),\r\n );\r\n }\r\n } else {\r\n bidPackageCopy.setRequirementFulfillment(\r\n bidValue.requirementId || '',\r\n new BidPackageRequirementFulfillment({\r\n id: generateUuid(),\r\n bidderId: bidValue.bidderId,\r\n price: price,\r\n classification: classification,\r\n value: value,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n }),\r\n );\r\n }\r\n }\r\n\r\n return bidPackageCopy;\r\n};\r\n\r\nconst onBlurCallback_RequirementFulfillment = (\r\n originalBidPackage: BidPackage,\r\n currentBidPackage: BidPackage,\r\n bidValue: RequirementFulfillmentBidValue,\r\n): ICommand | null => {\r\n const matchingBidder = currentBidPackage.bidders?.find(\r\n (v) => v.id === bidValue.bidderId,\r\n ) as Bidder;\r\n\r\n // NOTE: We get the original fulfillment from the copy of the selected bid package so we can compare the values\r\n const matchingRequirement = originalBidPackage?.requirements?.find(\r\n (v) => v.id === bidValue.requirementId,\r\n );\r\n\r\n if (!matchingRequirement) {\r\n return null;\r\n }\r\n\r\n const matchingExistingFulfillment = matchingRequirement.requirementFulfillments?.find(\r\n (v) => v.bidderId === bidValue.bidderId,\r\n );\r\n\r\n let fulfillmentShouldBeSet = false;\r\n let fulfillmentShouldBeDeleted = false;\r\n\r\n switch (matchingRequirement.requirementFulfillmentType) {\r\n // NOTE: Qualitative fulfillments don't require any validation, they're just a checkbox\r\n case RequirementFulfillmentTypes.Qualitative:\r\n // NOTE: A qualitative fulfillment existing counts as it having a value and vice versa,\r\n // but we also want to check that the fulfillment value\r\n fulfillmentShouldBeSet =\r\n matchingExistingFulfillment === undefined && (bidValue.value as boolean) === true;\r\n\r\n fulfillmentShouldBeDeleted =\r\n matchingExistingFulfillment !== undefined && (bidValue.value as boolean) === false;\r\n\r\n break;\r\n\r\n case RequirementFulfillmentTypes.Quantitative: {\r\n const isFulfillmentValid = BidPackageRequirementFulfillment.isBidValid(\r\n bidValue.price,\r\n bidValue.classification,\r\n );\r\n const isExistingFulfillmentValid =\r\n matchingExistingFulfillment !== undefined &&\r\n BidPackageRequirementFulfillment.isBidValid(\r\n matchingExistingFulfillment.price,\r\n matchingExistingFulfillment.classification,\r\n );\r\n\r\n // If the fulfillment was valid and changed from the previous one\r\n fulfillmentShouldBeSet =\r\n isFulfillmentValid &&\r\n (!matchingExistingFulfillment ||\r\n normalizeNullOrUndefined(bidValue.price) !==\r\n normalizeNullOrUndefined(matchingExistingFulfillment.price) ||\r\n bidValue.classification !== matchingExistingFulfillment.classification);\r\n\r\n fulfillmentShouldBeDeleted = isExistingFulfillmentValid && !isFulfillmentValid;\r\n\r\n break;\r\n }\r\n\r\n case RequirementFulfillmentTypes.Freeform: {\r\n const fulfillmentTextValue = ((bidValue.value as string) || '').trim();\r\n const isFulfillmentValid = fulfillmentTextValue.length > 0;\r\n\r\n // NOTE: This is case sensitive\r\n fulfillmentShouldBeSet =\r\n isFulfillmentValid &&\r\n (!matchingExistingFulfillment ||\r\n fulfillmentTextValue !== ((matchingExistingFulfillment.value as string) || '').trim());\r\n\r\n fulfillmentShouldBeDeleted = matchingExistingFulfillment !== undefined && !isFulfillmentValid;\r\n break;\r\n }\r\n }\r\n\r\n let commandToProcess: ICommand | null = null;\r\n\r\n if (fulfillmentShouldBeSet) {\r\n const commandToProcess2 = new SetBidderRequirementFulfillmentOnBidPackageCommand(\r\n currentBidPackage.id,\r\n matchingRequirement.description!,\r\n matchingRequirement.requirementType === 'Trade',\r\n matchingBidder.companyName!,\r\n matchingRequirement.requirementFulfillmentType as number,\r\n null,\r\n null,\r\n null,\r\n );\r\n\r\n switch (matchingRequirement.requirementFulfillmentType) {\r\n case RequirementFulfillmentTypes.Qualitative:\r\n // NOTE: We do not set anything for qualitative bids\r\n break;\r\n case RequirementFulfillmentTypes.Quantitative:\r\n commandToProcess2.price = bidValue.price !== undefined ? bidValue.price : null;\r\n commandToProcess2.classification =\r\n bidValue.classification || BidClassificationTypes.Unallocated;\r\n break;\r\n\r\n case RequirementFulfillmentTypes.Freeform:\r\n commandToProcess2.value = (bidValue.value as string) || null;\r\n break;\r\n }\r\n\r\n commandToProcess = commandToProcess2;\r\n } else if (fulfillmentShouldBeDeleted) {\r\n commandToProcess = new DeleteBidderRequirementFulfillmentOnBidPackageCommand(\r\n currentBidPackage.id,\r\n matchingRequirement.description!,\r\n matchingRequirement.requirementType === 'Trade',\r\n matchingBidder.companyName!,\r\n );\r\n }\r\n\r\n return commandToProcess;\r\n};\r\n\r\n// Updates data on a bid package\r\nconst successFunction_RequirementFulfillment = (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n // Delete the requirement fulfillment in the bid package copy\r\n if (command instanceof DeleteBidderRequirementFulfillmentOnBidPackageCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n const requirement = copy.getRequirementByDescription(\r\n command.isTradeRequirement,\r\n command.description,\r\n );\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n\r\n if (requirement && bidder) {\r\n copy.deleteRequirementFulfillment(requirement.id || '', bidder.id || '');\r\n }\r\n\r\n return copy;\r\n }\r\n // Add or update the requirement fulfillment\r\n else if (command instanceof SetBidderRequirementFulfillmentOnBidPackageCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n const requirement = copy.getRequirementByDescription(\r\n command.isTradeRequirement,\r\n command.description,\r\n );\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n\r\n if (requirement && bidder) {\r\n const fulfillmentToAddOrUpdate = clone(\r\n bidPackageWithUpdatedData.getRequirementFulfillment(\r\n requirement?.id || '',\r\n bidder?.id || '',\r\n ),\r\n );\r\n\r\n if (fulfillmentToAddOrUpdate) {\r\n copy.setRequirementFulfillment(requirement?.id || '', fulfillmentToAddOrUpdate);\r\n }\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\n// Restores data on a bid package\r\nconst errorFunction_RequirementFulfillment = (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n // Restore the line item bid in the bid package or delete it if it was new\r\n if (\r\n command instanceof DeleteBidderRequirementFulfillmentOnBidPackageCommand ||\r\n command instanceof SetBidderRequirementFulfillmentOnBidPackageCommand\r\n ) {\r\n const copy = clone(bidPackageToUpdate);\r\n const requirement = copy.getRequirementByDescription(\r\n command.isTradeRequirement,\r\n command.description,\r\n );\r\n const bidder = copy.getBidderByCompanyName(command.companyName);\r\n\r\n if (requirement && bidder) {\r\n const fulfillmentToRestore = clone(\r\n bidPackageWithUpdatedData.getRequirementFulfillment(requirement.id || '', bidder.id || ''),\r\n );\r\n\r\n if (fulfillmentToRestore) {\r\n copy.setRequirementFulfillment(requirement.id || '', fulfillmentToRestore);\r\n } else {\r\n copy.deleteRequirementFulfillment(requirement.id || '', bidder.id || '');\r\n }\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\nexport default useBidPackageBidHandler_RequirementFulfillments;\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class AddEditBidPackageNotesToBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public bidPackageNotesId: string | null,\r\n public text: string,\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.AddEditBidPackageNotes',\r\n '/bid-package/notes',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import React from 'react';\r\nimport { get } from 'lodash';\r\nimport { TextArea } from '@progress/kendo-react-inputs';\r\nimport { Field, FieldProps } from 'formik';\r\nimport './Forms.scss';\r\n\r\ninterface Props {\r\n label: string;\r\n name: string;\r\n onBlur?: (event: React.FocusEvent) => void;\r\n validator?: (value: string) => string | void;\r\n disabled?: boolean;\r\n isReadOnly?: boolean;\r\n tabIndex?: number;\r\n tooltip?: string;\r\n 'data-testid'?: string;\r\n}\r\n\r\nconst WrappedInput: React.FC = ({ field, form, label, onBlur, ...rest }) => {\r\n const errors = get(form.errors, field.name);\r\n const hasErrors = !!errors;\r\n\r\n const classNames = ['formInput'];\r\n if (hasErrors && form.submitCount) {\r\n classNames.push('formInputError');\r\n }\r\n\r\n return (\r\n <>\r\n \r\n {\r\n form.setFieldValue(field.name, e.value);\r\n }}\r\n />\r\n \r\n );\r\n};\r\n\r\nconst FormTextAreaInput: React.FC = ({\r\n name,\r\n label,\r\n validator,\r\n tabIndex,\r\n tooltip,\r\n isReadOnly,\r\n ...rest\r\n}) => {\r\n return (\r\n // TODO: move tooltip to the Kendo Input in WrappedInput\r\n // Kendo's Input isn't properly displaying a tooltip, but it looks fixed in newer versions\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default FormTextAreaInput;\r\n","import { Form, Formik } from 'formik';\r\nimport React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport * as Yup from 'yup';\r\nimport { getFormErrorMessages } from '../../../utils/forms';\r\nimport BTButton from '../controls/button/BTButton';\r\nimport FormErrorContainer from '../forms/form-error-container/FormErrorContainer';\r\nimport FormFooter from '../forms/FormFooter';\r\nimport FormTextAreaInput from '../forms/FormTextAreaInput';\r\nimport FrozenEntityNotification from '../frozen-entity-notification/FrozenEntityNotification';\r\nimport './BTNotes.scss';\r\n\r\ninterface Props {\r\n notes: string;\r\n title: string;\r\n entityName: string; // Used with the frozen entity notification\r\n maxLength: number;\r\n isReadOnly: boolean;\r\n isFrozen: boolean;\r\n onSubmitClick: (notes: string) => void;\r\n onCloseClick: (notes: string) => void;\r\n}\r\n\r\nconst BTNotes: React.FC = ({\r\n notes,\r\n title,\r\n entityName,\r\n maxLength,\r\n isReadOnly,\r\n isFrozen,\r\n onSubmitClick,\r\n onCloseClick,\r\n}) => {\r\n const { t } = useTranslation();\r\n\r\n const FormSchema = Yup.object().shape({\r\n notes: Yup.string()\r\n .trim()\r\n .max(maxLength, t('general:notesMaxLengthError', { maxLength: maxLength })),\r\n });\r\n\r\n return (\r\n <>\r\n {isFrozen ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n {\r\n onSubmitClick(values.notes);\r\n }}\r\n validationSchema={FormSchema}\r\n >\r\n {({ errors, values, submitCount, resetForm }): JSX.Element => (\r\n <>\r\n
    \r\n

    {title}

    \r\n\r\n {isReadOnly ? (\r\n
    {notes}
    \r\n ) : (\r\n \r\n )}\r\n\r\n
    \r\n {isReadOnly ? (\r\n <>\r\n ) : (\r\n <>\r\n \r\n\r\n onCloseClick(values.notes)}\r\n />\r\n \r\n )}\r\n
    \r\n \r\n {submitCount > 0 && (\r\n \r\n )}\r\n \r\n \r\n \r\n )}\r\n \r\n
    \r\n \r\n );\r\n};\r\n\r\nexport default BTNotes;\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class UpdateBidPackageLockCommand extends CommandBase {\r\n constructor(public bidPackageId: string, public lockedByUserEmail: string | null) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.UpdateLockedByUserEmail',\r\n 'bid-package/update-lock',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { clone } from 'lodash';\r\nimport React, { useCallback, useContext, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { AddEditBidPackageNotesToBidPackageCommand } from '../../../../../classes/commands/bid-packages/add-edit-bid-package-notes-to-bid-package-command';\r\nimport { ClearSelectedBidderOnBidPackage } from '../../../../../classes/commands/bid-packages/clear-selected-bidder-on-bid-package-command';\r\nimport { SetSelectedBidderOnBidPackage } from '../../../../../classes/commands/bid-packages/set-selected-bidder-on-bid-package-command';\r\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\r\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\r\nimport { CommandManagerService } from '../../../../../services/command/command-manager-service';\r\nimport { ConfirmationOverlayContext } from '../../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport BTModal from '../../../../common-page-components/modal/BTModal';\r\nimport BTNotes from '../../../../common-page-components/notes/BTNotes';\r\nimport { UpdateBidPackageLockCommand } from './../../../../../classes/commands/bid-packages/update-bid-package-lock-command';\r\n\r\ninterface ReturnValue {\r\n openBidPackageNotes: (bidPackageNotes: string) => void;\r\n getBidPackageNotesJSX: (\r\n bidPackage: BidPackage,\r\n isReadOnly: boolean,\r\n isFrozen: boolean,\r\n onBidPackageNotesChangeCallback: (functionToExecute: () => Promise) => void,\r\n ) => JSX.Element;\r\n\r\n // Updates the bid package copy with the new data from the current bid package\r\n successFunction_SelectedBidder: (command: ICommand, bidPackageToUpdate: BidPackage) => BidPackage;\r\n\r\n // Updates the current bid package with the data from the bid package copy\r\n errorFunction_SelectedBidder: (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n\r\n // Generates an updateBidPackageLockCommand\r\n onLockChangeCallback: (bidPackageId: string, lockedByUserEmail: string | null) => ICommand | null;\r\n\r\n // Updates the bid package copy with the new data from the current bid package\r\n successFunction_Lock: (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n\r\n // Updates the current bid package with the data from the bid package copy\r\n errorFunction_Lock: (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n}\r\n\r\ninterface BidPackageNotesModalState {\r\n isOpen: boolean;\r\n bidPackageNotesToEdit: string;\r\n}\r\n\r\nconst useBidPackage = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n\r\n const [bidPackageNotesModalState, setBidPackageNotesModalState] = useState<\r\n BidPackageNotesModalState\r\n >({ isOpen: false, bidPackageNotesToEdit: '' });\r\n\r\n const openBidPackageNotes = useCallback((bidPackageNotes: string) => {\r\n setBidPackageNotesModalState((curr) => ({\r\n ...curr,\r\n bidPackageNotesToEdit: bidPackageNotes,\r\n isOpen: true,\r\n }));\r\n }, []);\r\n\r\n const onBidPackageNotesDiscard = useCallback(\r\n (notes: string): void => {\r\n if (notes.trim() === bidPackageNotesModalState.bidPackageNotesToEdit.trim()) {\r\n setBidPackageNotesModalState((curr) => ({ ...curr, isOpen: false }));\r\n return;\r\n }\r\n\r\n showConfirmationOverlay({\r\n text: t('general:discardConfirmation'),\r\n buttons: [\r\n {\r\n text: t('general:discard'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n setBidPackageNotesModalState((curr) => ({ ...curr, isOpen: false }));\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:cancel'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n },\r\n [showConfirmationOverlay, hideConfirmationOverlay, t, bidPackageNotesModalState],\r\n );\r\n\r\n const onBidPackageNotesChange = useCallback(\r\n async (\r\n bidPackage: BidPackage,\r\n newNotes: string,\r\n onBidPackageNotesChangeCallback: (\r\n functionToExecute: () => Promise,\r\n ) => void,\r\n ): Promise => {\r\n if (bidPackage.notesId === undefined) {\r\n return;\r\n }\r\n\r\n onBidPackageNotesChangeCallback(\r\n async (): Promise => {\r\n newNotes = newNotes.trim();\r\n\r\n const response = await CommandManagerService.executeCommand(\r\n new AddEditBidPackageNotesToBidPackageCommand(\r\n bidPackage.id,\r\n bidPackage.notesId!,\r\n newNotes,\r\n ),\r\n );\r\n\r\n if (response) {\r\n setBidPackageNotesModalState({\r\n isOpen: false,\r\n bidPackageNotesToEdit: newNotes,\r\n });\r\n\r\n const copy = clone(bidPackage);\r\n copy.notes = newNotes;\r\n copy.notesId = response.data;\r\n return copy;\r\n }\r\n\r\n return null;\r\n },\r\n );\r\n },\r\n [],\r\n );\r\n\r\n const onBidPackageNotesModalClose = useCallback(() => {\r\n setBidPackageNotesModalState((curr) => ({ ...curr, isOpen: false }));\r\n }, []);\r\n\r\n const getBidPackageNotesJSX = useCallback(\r\n (\r\n bidPackage: BidPackage,\r\n isReadOnly: boolean,\r\n isFrozen: boolean,\r\n onBidPackageNotesChangeCallback: (\r\n functionToExecute: () => Promise,\r\n ) => void,\r\n ): JSX.Element => {\r\n return (\r\n \r\n {\r\n onBidPackageNotesChange(bidPackage, notes, onBidPackageNotesChangeCallback);\r\n }}\r\n onCloseClick={onBidPackageNotesDiscard}\r\n maxLength={EntityValidationConstants.BidPackageEntityLimits.Notes_MaxLength}\r\n />\r\n \r\n );\r\n },\r\n [\r\n bidPackageNotesModalState.bidPackageNotesToEdit,\r\n bidPackageNotesModalState.isOpen,\r\n onBidPackageNotesChange,\r\n onBidPackageNotesDiscard,\r\n onBidPackageNotesModalClose,\r\n t,\r\n ],\r\n );\r\n\r\n // Updates data on a bid package\r\n const successFunction_SelectedBidder = useCallback(\r\n (command: ICommand, bidPackageToUpdate: BidPackage): BidPackage => {\r\n // Delete the line item rollup bid in the bid package copy\r\n if (command instanceof ClearSelectedBidderOnBidPackage) {\r\n const copy = clone(bidPackageToUpdate);\r\n\r\n if (copy.selectedBidderId) {\r\n copy.clearSelectedBidder();\r\n }\r\n\r\n return copy;\r\n } else if (command instanceof SetSelectedBidderOnBidPackage) {\r\n const copy = clone(bidPackageToUpdate);\r\n const bidder = copy.getBidderByCompanyName(command.selectedBidderCompanyName || '');\r\n\r\n if (bidder) {\r\n copy.setSelectedBidder(bidder.id || '');\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n },\r\n [],\r\n );\r\n\r\n // Updates data on a bid package\r\n const errorFunction_SelectedBidder = useCallback(\r\n (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ): BidPackage => {\r\n const copy = clone(bidPackageToUpdate);\r\n\r\n // Restore the previously selected bidder or clear it if it wasn't previously set\r\n if (\r\n command instanceof ClearSelectedBidderOnBidPackage ||\r\n command instanceof SetSelectedBidderOnBidPackage\r\n ) {\r\n const previouslySelectedBidderId = bidPackageWithUpdatedData.selectedBidderId;\r\n if (previouslySelectedBidderId) {\r\n copy.setSelectedBidder(previouslySelectedBidderId);\r\n } else {\r\n copy.clearSelectedBidder();\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n },\r\n [],\r\n );\r\n\r\n // Returns an updatedBidPackageLockCommand\r\n const onLockChangeCallback = (bidPackageId: string, email: string | null): ICommand | null => {\r\n return new UpdateBidPackageLockCommand(bidPackageId, email?.trim() ?? null);\r\n };\r\n\r\n // Updates the lock on a bid package\r\n const successFunction_Lock = (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ): BidPackage => {\r\n if (command instanceof UpdateBidPackageLockCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n copy.lockedByUserEmail = bidPackageWithUpdatedData.lockedByUserEmail;\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n };\r\n\r\n const errorFunction_Lock = (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ): BidPackage => {\r\n if (command instanceof UpdateBidPackageLockCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n copy.lockedByUserEmail = bidPackageWithUpdatedData.lockedByUserEmail;\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n };\r\n\r\n return {\r\n getBidPackageNotesJSX,\r\n openBidPackageNotes,\r\n successFunction_SelectedBidder,\r\n errorFunction_SelectedBidder,\r\n onLockChangeCallback,\r\n successFunction_Lock,\r\n errorFunction_Lock,\r\n };\r\n};\r\n\r\nexport default useBidPackage;\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class AddEditAdjustmentNotesToBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public adjustmentNotesId: string | null,\r\n public companyName: string,\r\n public alternateName: string | null,\r\n public text: string,\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.AddEditAdjustmentNotes',\r\n '/bid-package/add-adjustment-notes',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { clone } from 'lodash';\nimport React, { useCallback, useContext, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AddEditAdjustmentNotesToBidPackageCommand } from '../../../../../classes/commands/bid-packages/add-edit-adjustment-notes-to-bid-package-command';\nimport { Adjustment } from '../../../../../classes/odata/adjustment';\nimport { Alternate } from '../../../../../classes/odata/alternate';\nimport { Bidder } from '../../../../../classes/odata/bidder';\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\nimport { CommandManagerService } from '../../../../../services/command/command-manager-service';\nimport { useLogger } from '../../../../../services/logger/Logger';\nimport { ConfirmationOverlayContext } from '../../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport { LoadingPageOverlayContext } from '../../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\nimport BTModal from '../../../../common-page-components/modal/BTModal';\nimport BTNotes from '../../../../common-page-components/notes/BTNotes';\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\nimport useBidPackagePageContext from '../BidPackagePageContext';\n\ninterface ReturnValue {\n editAdjustmentNotes: (adjustment: Adjustment) => void;\n getAdjustmentNotesJSX: (\n isReadOnly: boolean,\n isFrozen: boolean,\n alternates: Alternate[],\n bidders: Bidder[],\n ) => JSX.Element;\n}\n\ninterface ModalState {\n isOpen: boolean;\n adjustmentToEdit: Adjustment | null;\n}\n\nconst useBidPackageAdjustments_Notes = (): ReturnValue => {\n const { t } = useTranslation();\n\n const logger = useLogger();\n\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\n\n const { showSuccessNotification, showErrorNotification } = useContext(NotificationPanelContext);\n\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n\n const { adjustment_SaveNote } = useBidPackagePageContext();\n\n const [modalState, setModalState] = useState({\n isOpen: false,\n adjustmentToEdit: null,\n });\n\n const editAdjustmentNotes = useCallback((adjustment: Adjustment) => {\n const adjustmentToEdit = clone(adjustment);\n adjustmentToEdit.notes = adjustmentToEdit.notes || '';\n\n setModalState({\n isOpen: true,\n adjustmentToEdit: adjustmentToEdit,\n });\n }, []);\n\n const closeAdjustmentNotesModal = useCallback(() => {\n setModalState((curr) => ({ ...curr, isOpen: false }));\n }, [setModalState]);\n\n const onAdjustmentNotesSave = useCallback(\n async (newNotes: string, alternates: Alternate[], bidders: Bidder[]): Promise => {\n try {\n if (!modalState.adjustmentToEdit) {\n return;\n }\n\n const companyName =\n bidders.find((v) => v.id === modalState.adjustmentToEdit?.bidderId)?.companyName || '';\n\n if (!modalState.adjustmentToEdit.bidPackageId || !companyName) {\n return;\n }\n\n newNotes = (newNotes || '').trim();\n\n showPageLoadingOverlay();\n\n const matchingAlternate = alternates.find(\n (v) => v.id === modalState.adjustmentToEdit?.alternateId,\n );\n\n const response = await CommandManagerService.executeCommand(\n new AddEditAdjustmentNotesToBidPackageCommand(\n modalState.adjustmentToEdit.bidPackageId,\n // NOTE: The adjustment object will have a notes ID if it exists already on the server\n modalState.adjustmentToEdit.notesId ?? null,\n companyName,\n matchingAlternate?.name || null,\n newNotes.trim(),\n ),\n );\n\n if (!response) {\n throw Error(t('bid-package:errorAddNotes'));\n }\n\n closeAdjustmentNotesModal();\n\n const copy = clone(modalState.adjustmentToEdit);\n copy.notes = newNotes;\n copy.notesId = response.data;\n\n adjustment_SaveNote(copy);\n\n showSuccessNotification(t('general:success'), t('bid-package:successSetNotes'));\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('bid-package:errorAddNotes'));\n } finally {\n hidePageLoadingOverlay();\n }\n },\n [\n adjustment_SaveNote,\n closeAdjustmentNotesModal,\n hidePageLoadingOverlay,\n logger,\n modalState.adjustmentToEdit,\n showErrorNotification,\n showPageLoadingOverlay,\n showSuccessNotification,\n t,\n ],\n );\n\n const onAdjustmentNotesDiscard = useCallback(\n (notes: string): void => {\n if (!modalState.adjustmentToEdit) {\n return;\n }\n\n if (notes.trim() === modalState.adjustmentToEdit.notes!.trim()) {\n closeAdjustmentNotesModal();\n return;\n }\n\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: (): void => {\n hideConfirmationOverlay();\n closeAdjustmentNotesModal();\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n },\n [\n closeAdjustmentNotesModal,\n hideConfirmationOverlay,\n modalState.adjustmentToEdit,\n showConfirmationOverlay,\n t,\n ],\n );\n\n const getAdjustmentNotesJSX = useCallback(\n (\n isReadOnly: boolean,\n isFrozen: boolean,\n alternates: Alternate[],\n bidders: Bidder[],\n ): JSX.Element => {\n return modalState.adjustmentToEdit ? (\n \n onAdjustmentNotesSave(notes, alternates, bidders)}\n onCloseClick={onAdjustmentNotesDiscard}\n maxLength={EntityValidationConstants.AdjustmentEntityLimits.Notes_MaxLength}\n />\n \n ) : (\n <>\n );\n },\n [\n modalState.adjustmentToEdit,\n modalState.isOpen,\n closeAdjustmentNotesModal,\n t,\n onAdjustmentNotesSave,\n onAdjustmentNotesDiscard,\n ],\n );\n\n return {\n editAdjustmentNotes,\n getAdjustmentNotesJSX,\n };\n};\n\nexport default useBidPackageAdjustments_Notes;\n","import { CommandBase } from '../CommandBase';\n\nexport class AddBidderToBidPackageCommand extends CommandBase {\n constructor(\n public bidPackageId: string,\n public companyName: string,\n public primaryContactName: string,\n public primaryContactEmail: string,\n public phoneNumber: string,\n public faxNumber: string | undefined,\n ) {\n super('DESTINI.BidDay.Commands.BidPackages.AddBidderToBidPackage', '', 'none');\n }\n}\n","import { CommandBase } from '../CommandBase';\n\nexport class UpdateBidPackageBidderCommand extends CommandBase {\n constructor(\n public bidPackageId: string,\n public originalCompanyName: string,\n public companyName?: string,\n public primaryContactName?: string,\n public primaryContactEmail?: string,\n public phoneNumber?: string,\n public faxNumber?: string,\n ) {\n super('DESTINI.BidDay.Commands.BidPackages.UpdateBidPackageBidder', '', 'none');\n }\n}\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n Grid,\n GridCellProps,\n GridColumn,\n GridItemChangeEvent,\n GridNoRecords,\n GridToolbar,\n} from '@progress/kendo-react-grid';\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AddBidderToBidPackageCommand } from '../../../../../classes/commands/bid-packages/add-bidder-to-bid-package-command';\nimport { UpdateBidPackageBidderCommand } from '../../../../../classes/commands/bid-packages/update-bid-package-bidder-command';\nimport { Bidder } from '../../../../../classes/odata/bidder';\nimport GeneralConstants from '../../../../../constants/general';\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\nimport { nameof } from '../../../../../utils/nameof';\nimport {\n getDuplicates,\n getSanitizedExcelRows,\n isEmptyOrWhitespace,\n isValidEmail,\n isValidPhoneNumber,\n} from '../../../../../utils/strings';\nimport { generateUuid } from '../../../../../utils/uuid';\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\nimport FormErrorContainer from '../../../../common-page-components/forms/form-error-container/FormErrorContainer';\nimport FormFooter from '../../../../common-page-components/forms/FormFooter';\nimport BTItemsManagerGridTextCell, {\n GridCellValidatorFunction,\n} from '../../../../common-page-components/items-manager-grid/cells/BTItemsManagerGridTextCell';\nimport './AddEditBiddersForm.scss';\n\nexport const GridTestIdPrefix = 'addedit-bidders-grid';\n\ninterface Props {\n bidPackageId: string;\n existingBidders: Bidder[] | undefined;\n mode: 'add' | 'edit';\n bidderToEdit?: Bidder;\n onSaveClick: (commands: AddBidderToBidPackageCommand[] | UpdateBidPackageBidderCommand[]) => void;\n onDiscardClick: (mode: 'add' | 'edit', bidders: Bidder[]) => void;\n onEditedBiddersChange: (bidders: Bidder[]) => void;\n}\n\ninterface ParsedRowData {\n companyName: string;\n primaryContactName: string;\n primaryContactEmail: string;\n phoneNumber: string;\n faxNumber: string;\n}\n\nconst AddEditBiddersForm: React.FC = ({\n bidPackageId,\n existingBidders,\n mode,\n bidderToEdit,\n onSaveClick,\n onDiscardClick,\n onEditedBiddersChange,\n}) => {\n const isAddMode = mode === 'add';\n\n const { t } = useTranslation();\n const [bidders, setBidders] = useState(\n mode === 'edit' && bidderToEdit\n ? [new Bidder({ ...bidderToEdit, originalCompanyName: bidderToEdit.companyName })]\n : [],\n );\n const [errors, setErrors] = useState([]);\n\n useEffect(() => {\n onEditedBiddersChange(bidders);\n }, [bidders, onEditedBiddersChange]);\n\n const getCommands = useCallback(():\n | AddBidderToBidPackageCommand[]\n | UpdateBidPackageBidderCommand[] => {\n if (isAddMode) {\n if (!bidders.length) {\n return [];\n }\n\n const commands = bidders.map(\n (b) =>\n new AddBidderToBidPackageCommand(\n b.bidPackageId!,\n b.companyName!.trim(),\n b.primaryContactName!.trim(),\n b.primaryContactEmail!.trim(),\n b.phoneNumber!.trim(),\n b.faxNumber?.trim(),\n ),\n );\n return commands;\n } else if (mode === 'edit') {\n const commands = bidders.map((b) => {\n // This is done so that we aren't passing unchanged values to the command\n const companyName = bidderToEdit!.companyName !== b.companyName ? b.companyName : undefined;\n const primaryContactName =\n bidderToEdit!.primaryContactName !== b.primaryContactName\n ? b.primaryContactName\n : undefined;\n const primaryContactEmail =\n bidderToEdit!.primaryContactEmail !== b.primaryContactEmail\n ? b.primaryContactEmail\n : undefined;\n const phoneNumber = bidderToEdit!.phoneNumber !== b.phoneNumber ? b.phoneNumber : undefined;\n const faxNumber = bidderToEdit!.faxNumber !== b.faxNumber ? b.faxNumber : undefined;\n\n return new UpdateBidPackageBidderCommand(\n b.bidPackageId!,\n b.originalCompanyName!,\n companyName?.trim(),\n primaryContactName?.trim(),\n primaryContactEmail?.trim(),\n phoneNumber?.trim(),\n faxNumber?.trim(),\n );\n });\n\n return commands;\n } else {\n throw new Error(`Invalid mode ${mode}`);\n }\n }, [bidderToEdit, bidders, isAddMode, mode]);\n\n const onAddClick = useCallback(() => {\n if (!isAddMode) {\n return;\n }\n\n const newBidder = new Bidder({\n id: generateUuid(),\n bidPackageId: bidPackageId,\n companyName: '',\n primaryContactName: '',\n primaryContactEmail: '',\n phoneNumber: '',\n faxNumber: '',\n inEdit: true,\n });\n setBidders((bidders) => bidders.concat(newBidder));\n }, [bidPackageId, isAddMode]);\n\n const onDeleteClick = useCallback(\n (bidder: Bidder) => {\n setBidders((bidders) => bidders.filter((sb) => !(sb.id === bidder.id)));\n },\n [setBidders],\n );\n\n const onItemChanged = useCallback(\n (e: GridItemChangeEvent) => {\n const editedBidder = e.dataItem as Bidder;\n\n const editedBidders = bidders.map((b) =>\n b.id === editedBidder.id ? new Bidder({ ...editedBidder, [e.field ?? '']: e.value }) : b,\n );\n\n setBidders(editedBidders);\n },\n [bidders],\n );\n\n const onPaste = useCallback(\n (e: React.ClipboardEvent) => {\n const clipboardData = e.clipboardData.getData('text');\n const rows = getSanitizedExcelRows(clipboardData);\n\n // If the user is pasting in text without any special characters that we parse, let them paste it\n if (rows?.length === 1 && rows[0].length === 1) {\n return;\n }\n\n // Prevent the event from bubbling, since we are handling the paste event entirely here\n e.preventDefault();\n e.stopPropagation();\n\n // For certain cells, we tack on the column index of the cell\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const eventAsAny = e as any;\n const columnIndexOfOriginCell = eventAsAny.columnIndex ?? null;\n const rowIndexOfOriginCell = eventAsAny.rowIndex ?? null;\n\n const parseBidderInputsFromRow = (rowData: string[]): ParsedRowData => {\n const returnValue: ParsedRowData = {\n companyName: (rowData[0] || '').slice(\n 0,\n EntityValidationConstants.BidderEntityLimits.CompanyName_MaxLength,\n ),\n primaryContactName: (rowData[1] || '').slice(\n 0,\n EntityValidationConstants.BidderEntityLimits.PrimaryContactName_MaxLength,\n ),\n primaryContactEmail: (rowData[2] || '').slice(\n 0,\n EntityValidationConstants.BidderEntityLimits.PrimaryContactEmail_MaxLength,\n ),\n phoneNumber: (rowData[3] || '').slice(\n 0,\n EntityValidationConstants.BidderEntityLimits.PhoneNumber_MaxLength,\n ),\n faxNumber: (rowData[4] || '').slice(\n 0,\n EntityValidationConstants.BidderEntityLimits.FaxNumber_MaxLength,\n ),\n };\n\n return returnValue;\n };\n\n // If the user pasted into a cell in an existing row, and the clipboard contained a single row of data with multiple cells,\n // paste the data starting at the specified cell, on the specified row\n if (columnIndexOfOriginCell >= 0 && rows?.length === 1 && rows[0].length > 1) {\n // Pad the rows collection for the cells prior to the one that was pasted into\n for (let i = columnIndexOfOriginCell - 1; i >= 0; i--) {\n switch (i) {\n case 0:\n rows[0].unshift(bidders[rowIndexOfOriginCell]?.companyName || '');\n break;\n\n case 1:\n rows[0].unshift(bidders[rowIndexOfOriginCell]?.primaryContactName || '');\n break;\n\n case 2:\n rows[0].unshift(bidders[rowIndexOfOriginCell]?.primaryContactEmail || '');\n break;\n\n case 3:\n rows[0].unshift(bidders[rowIndexOfOriginCell]?.phoneNumber || '');\n break;\n\n case 4:\n rows[0].unshift(bidders[rowIndexOfOriginCell]?.faxNumber || '');\n break;\n }\n }\n\n const parsedRowData = parseBidderInputsFromRow(rows[0]);\n\n // Update the existing line item\n if (rowIndexOfOriginCell !== null) {\n setBidders((currBidders) => {\n const newBiddersArray = [...currBidders];\n newBiddersArray[rowIndexOfOriginCell] = new Bidder({\n ...newBiddersArray[rowIndexOfOriginCell],\n ...parsedRowData,\n });\n\n return newBiddersArray;\n });\n\n // Blur the input that triggered the paste event, so Kendo displays the new values\n if (e.target && (e.target as HTMLInputElement).blur) {\n (e.target as HTMLInputElement).blur();\n }\n\n return;\n }\n }\n\n // NOTE: If we are in edit mode, we let the user paste multiple cells into a row, but we don't allow pasting multiple rows\n // of data, as we don't want to be able to add bidders in edit mode\n if (!isAddMode && (rows?.length || 0) > 1) {\n return;\n }\n\n if (rows) {\n const result = rows.map((currRow) => {\n const parsedRowDataForCurrRow = parseBidderInputsFromRow(currRow);\n\n return new Bidder({\n id: generateUuid(),\n bidPackageId: bidPackageId,\n ...parsedRowDataForCurrRow,\n inEdit: true,\n });\n });\n\n // Add in the new rows and remove any empty rows\n setBidders((bidders) => {\n return bidders.concat(result).filter((v) => {\n return (\n !isEmptyOrWhitespace(v.companyName) ||\n !isEmptyOrWhitespace(v.primaryContactName) ||\n !isEmptyOrWhitespace(v.primaryContactEmail) ||\n !isEmptyOrWhitespace(v.phoneNumber) ||\n !isEmptyOrWhitespace(v.faxNumber)\n );\n });\n });\n\n // Blur the input that triggered the paste event, so Kendo displays the new values\n if (e.target && (e.target as HTMLInputElement).blur) {\n (e.target as HTMLInputElement).blur();\n }\n }\n },\n [bidPackageId, bidders, isAddMode],\n );\n\n const requiredTextInput = useCallback((gcp: GridCellProps): JSX.Element => {\n let autoFocus = false;\n let maxLength: number | undefined = undefined;\n let validationFn: GridCellValidatorFunction | null = null;\n\n switch (gcp.field) {\n case nameof('companyName'):\n autoFocus = true;\n maxLength = EntityValidationConstants.BidderEntityLimits.CompanyName_MaxLength;\n break;\n\n case nameof('phoneNumber'):\n maxLength = EntityValidationConstants.BidderEntityLimits.PhoneNumber_MaxLength;\n validationFn = (currValue) => isValidPhoneNumber(currValue);\n break;\n\n case nameof('primaryContactEmail'):\n maxLength = EntityValidationConstants.BidderEntityLimits.PrimaryContactEmail_MaxLength;\n validationFn = (currValue) => isValidEmail(currValue);\n break;\n\n case nameof('primaryContactName'):\n maxLength = EntityValidationConstants.BidderEntityLimits.PrimaryContactName_MaxLength;\n break;\n }\n\n return (\n {\n // Add in the columnIndex / rowIndex to the event so we have that in the main paste handler code so we know where the\n // paste originated from\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const eventAsAny = e as any;\n\n eventAsAny.columnIndex = gcp.columnIndex;\n eventAsAny.rowIndex = gcp.dataIndex;\n }}\n />\n );\n }, []);\n\n const textInput = useCallback((gcp: GridCellProps): JSX.Element => {\n const isFaxNumberField = gcp.field === nameof('faxNumber');\n\n const maxLength: number | undefined = isFaxNumberField\n ? EntityValidationConstants.BidderEntityLimits.FaxNumber_MaxLength\n : undefined;\n\n const validationFn: GridCellValidatorFunction | null = isFaxNumberField\n ? (currValue) => {\n const cleanedUpValue = (currValue || '').trim();\n\n // If the value was empty, then do not apply any validation\n if (!cleanedUpValue) {\n return true;\n }\n\n return isValidPhoneNumber(cleanedUpValue);\n }\n : null;\n\n return (\n {\n // Add in the columnIndex / rowIndex to the event so we have that in the main paste handler code so we know where the\n // paste originated from\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const eventAsAny = e as any;\n\n eventAsAny.columnIndex = gcp.columnIndex;\n eventAsAny.rowIndex = gcp.dataIndex;\n }}\n />\n );\n }, []);\n\n const deleteButton = useCallback(\n (props: GridCellProps) => {\n const bidder = props.dataItem as Bidder;\n\n return (\n \n {\n onDeleteClick(bidder);\n }}\n >\n \n \n \n );\n },\n [onDeleteClick, t],\n );\n\n const validateBidders = useCallback((): boolean => {\n setErrors([]);\n const validationErrors: string[] = [];\n\n const missingName = bidders.find((b) => !b?.companyName?.trim());\n if (missingName) {\n validationErrors.push(t('bid-package:bidderNameRequired'));\n }\n\n // Check for duplicate Names\n const names: string[] = [\n ...(existingBidders || []).map((b) => b.companyName?.toLowerCase() as string),\n ...bidders.filter((b) => b.companyName).map((b) => b.companyName?.toLowerCase() as string),\n ];\n const duplicateNames: string[] = getDuplicates(names);\n\n // In edit mode, remove the original company name from the list of duplicates\n // so we don't get the unique name error\n if (mode === 'edit') {\n const bidderInEdit = bidders[0];\n if (bidderInEdit) {\n const indexOfOriginalCompanyName = duplicateNames.indexOf(\n bidderInEdit.originalCompanyName!.toLowerCase(),\n );\n\n if (indexOfOriginalCompanyName !== -1) {\n duplicateNames.splice(indexOfOriginalCompanyName, 1);\n }\n }\n }\n\n if (duplicateNames?.length) {\n validationErrors.push(t('bid-package:bidderUniqueNames'));\n }\n\n const missingContact = bidders.find((b) => !b?.primaryContactName?.trim());\n if (missingContact) {\n validationErrors.push(t('bid-package:bidderContactRequired'));\n }\n\n const missingEmail = bidders.find((b) => !b?.primaryContactEmail?.trim());\n if (missingEmail) {\n validationErrors.push(t('bid-package:bidderEmailRequired'));\n }\n\n const invalidEmails = bidders.find(\n (b) => b.primaryContactEmail && !isValidEmail(b.primaryContactEmail),\n );\n if (invalidEmails) {\n validationErrors.push(t('bid-package:bidderInvalidEmail'));\n }\n\n const missingPhone = bidders.find((b) => !b?.phoneNumber?.trim());\n if (missingPhone) {\n validationErrors.push(t('bid-package:bidderPhoneRequired'));\n }\n\n const invalidPhoneNumbers = bidders.find(\n (b) => b.phoneNumber && !isValidPhoneNumber(b.phoneNumber),\n );\n if (invalidPhoneNumbers) {\n validationErrors.push(t('bid-package:bidderInvalidPhone'));\n }\n\n const invalidFaxNumbers = bidders.find((b) => b.faxNumber && !isValidPhoneNumber(b.faxNumber));\n if (invalidFaxNumbers) {\n validationErrors.push(t('bid-package:bidderInvalidFax'));\n }\n\n setErrors(validationErrors);\n return validationErrors.length === 0;\n }, [bidders, existingBidders, mode, t]);\n\n const validateAndSave = useCallback(() => {\n const success = validateBidders();\n if (success) {\n onSaveClick(getCommands());\n }\n }, [getCommands, onSaveClick, validateBidders]);\n\n return useMemo(() => {\n return (\n
    \n

    {isAddMode ? t('bid-package:addSubs') : t('bid-package:editSub')}

    \n {\n if (isAddMode && e.key.toUpperCase() === GeneralConstants.KEY_N && e.altKey) {\n onAddClick();\n }\n }}\n >\n \n {isAddMode ? (\n \n \n \n \n \n ) : (\n <>\n )}\n\n \n\n \n\n \n\n \n\n \n\n {isAddMode ? : <>}\n\n {/* NOTE: We only allow the user to paste things in 'add' mode */}\n {isAddMode ? (\n \n
    \n
    \n \n
    \n \n
    \n\n
    {t('general:pasteClipboardDataToCreateBiddersMessage')}
    \n
    \n
    \n ) : (\n <>\n )}\n \n \n
    \n\n \n
    \n \n\n onDiscardClick(mode, bidders)}\n />\n
    \n
    \n \n );\n }, [\n bidders,\n deleteButton,\n errors,\n isAddMode,\n mode,\n onAddClick,\n onDiscardClick,\n onItemChanged,\n onPaste,\n requiredTextInput,\n t,\n textInput,\n validateAndSave,\n ]);\n};\n\nexport default AddEditBiddersForm;\n","import { isEqual, omit } from 'lodash';\nimport React, { useCallback, useContext, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AddBidderToBidPackageCommand } from '../../../../../classes/commands/bid-packages/add-bidder-to-bid-package-command';\nimport { UpdateBidPackageBidderCommand } from '../../../../../classes/commands/bid-packages/update-bid-package-bidder-command';\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\nimport { Bidder } from '../../../../../classes/odata/bidder';\nimport { BidPackageApi } from '../../../../../services';\nimport { nameof } from '../../../../../utils/nameof';\nimport { ConfirmationOverlayContext } from '../../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport BTModal from '../../../../common-page-components/modal/BTModal';\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\nimport AddEditBiddersForm from '../components/AddEditBiddersForm';\n\ninterface ReturnValue {\n addBidders: () => void;\n editBidder: (bidder: Bidder) => void;\n getBiddersAddEditJSX: (bidPackage: BidPackage) => JSX.Element;\n}\n\ninterface ModalState {\n isOpen: boolean;\n mode: 'add' | 'edit';\n bidderToEdit?: Bidder;\n}\n\nconst initialModalState: ModalState = {\n isOpen: false,\n mode: 'add',\n};\n\nconst useBidPackageBidders_AddEditForm = (\n onBiddersSaveCallback: (functionToExecute: () => Promise) => void,\n): ReturnValue => {\n const { t } = useTranslation();\n\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n\n const { showInfoNotification } = useContext(NotificationPanelContext);\n\n const [modalState, setModalState] = useState(initialModalState);\n\n // We maintain a copy of the edited bidders in this parent component, so we can\n // tell when things changed in the modal closing logic\n const editedBidders = useRef([]);\n\n const addBidders = useCallback(() => {\n setModalState({ isOpen: true, mode: 'add' });\n }, []);\n\n const editBidder = useCallback((bidder: Bidder) => {\n setModalState({ isOpen: true, mode: 'edit', bidderToEdit: bidder });\n }, []);\n\n const onBiddersSave = useCallback(\n async (commands: AddBidderToBidPackageCommand[] | UpdateBidPackageBidderCommand[]) => {\n if (!commands.length) {\n showInfoNotification(t('general:noChanges'), t('bid-package:noChangesWereMade'));\n return;\n }\n\n if (modalState.mode === 'add') {\n const addCommands = commands as AddBidderToBidPackageCommand[];\n\n onBiddersSaveCallback(async () => {\n await BidPackageApi.addBiddersToBidPackage(addCommands);\n setModalState(initialModalState);\n });\n } else if (modalState.mode === 'edit') {\n const editCommands = commands as UpdateBidPackageBidderCommand[];\n\n onBiddersSaveCallback(async () => {\n await BidPackageApi.updateBidPackageBidders(editCommands);\n setModalState(initialModalState);\n });\n } else {\n throw new Error(`Unsupported Bidder mode '${modalState.mode}'`);\n }\n },\n [modalState.mode, onBiddersSaveCallback, showInfoNotification, t],\n );\n\n const shouldDiscardBidderChanges = useCallback(\n (mode: 'add' | 'edit', bidders: Bidder[]): Promise => {\n const editFieldsToOmit = [nameof('inEdit'), nameof('originalCompanyName')];\n\n return new Promise((resolve) => {\n if (\n // If we're in add mode and there are no bidders, it's safe to discard\n (mode === 'add' && !bidders.length) ||\n // If we're in edit mode and the bidder has not been modified, it's safe to discard\n (mode === 'edit' &&\n bidders[0] &&\n isEqual(\n omit(bidders[0], editFieldsToOmit),\n omit(modalState.bidderToEdit, editFieldsToOmit),\n ))\n ) {\n resolve(true);\n } else {\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: (): void => {\n hideConfirmationOverlay();\n resolve(true);\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n resolve(false);\n },\n color: 'gray',\n },\n ],\n });\n }\n });\n },\n [hideConfirmationOverlay, modalState.bidderToEdit, showConfirmationOverlay, t],\n );\n\n const onBiddersDiscarded = useCallback(\n async (mode: 'add' | 'edit', bidders: Bidder[]) => {\n const result = await shouldDiscardBidderChanges(mode, bidders);\n\n if (result) {\n setModalState(initialModalState);\n }\n },\n [shouldDiscardBidderChanges],\n );\n\n const onEditedBiddersChange = useCallback(async (bidders: Bidder[]) => {\n editedBidders.current = bidders;\n }, []);\n\n const getBiddersAddEditJSX = useCallback(\n (bidPackage: BidPackage): JSX.Element => {\n return (\n setModalState(initialModalState)}\n onModalClosing={async () => {\n return shouldDiscardBidderChanges(modalState.mode, editedBidders.current);\n }}\n addExtraSpaceAtBottom\n >\n \n \n );\n },\n [\n modalState.bidderToEdit,\n modalState.isOpen,\n modalState.mode,\n onBiddersDiscarded,\n onBiddersSave,\n onEditedBiddersChange,\n shouldDiscardBidderChanges,\n ],\n );\n\n return {\n addBidders,\n editBidder,\n getBiddersAddEditJSX,\n };\n};\n\nexport default useBidPackageBidders_AddEditForm;\n","import { CommandBase } from '../CommandBase';\n\nexport class DeleteBidPackageBidderDocumentCommand extends CommandBase {\n constructor(\n public bidPackageId: string,\n public bidderCompanyName: string,\n public fileName: string,\n ) {\n super(\n 'DESTINI.BidDay.Commands.Application.BidPackages.DeleteBidPackageBidderDocument',\n 'bid-package/file-uploads/delete-bidder-document',\n 'post',\n );\n }\n}\n","import React, { useState, useEffect } from 'react';\nimport {\n Upload,\n UploadFileInfo,\n UploadHttpHeaders,\n UploadOnAddEvent,\n UploadOnBeforeUploadEvent,\n UploadOnStatusChangeEvent,\n} from '@progress/kendo-react-upload';\nimport { CommandHttpService } from '../../../services/command/command-http-service';\nimport './BTUpload.scss';\n\ninterface Props {\n saveUrl?: string;\n // Will be attached as form data on each request\n additionalFormData?: { [name: string]: string };\n autoUpload?: boolean;\n multiple?: boolean;\n batch?: boolean;\n onAdd?: (files: UploadFileInfo[]) => void;\n onBeforeFileUpload?: (fileNames: string[]) => void;\n onFileUploadComplete?: () => void;\n}\n\nconst BTUpload: React.FC = (props) => {\n const [authHeaders, setAuthHeaders] = useState(null);\n\n useEffect(() => {\n const setHeaders = async () => {\n const headers = await CommandHttpService.getAuthHeaders();\n setAuthHeaders((headers as unknown) as UploadHttpHeaders);\n };\n\n setHeaders();\n }, []);\n\n const onAdd = (event: UploadOnAddEvent) => {\n if (props.onAdd) {\n const files = event.newState;\n props.onAdd(files);\n }\n };\n\n const onBeforeUpload = (event: UploadOnBeforeUploadEvent) => {\n if (props.additionalFormData) {\n event.additionalData = props.additionalFormData;\n }\n\n if (props.onBeforeFileUpload) {\n const fileNames = event.files?.map((fu) => fu.name);\n props.onBeforeFileUpload(fileNames);\n }\n };\n\n const onStatusChange = (event: UploadOnStatusChangeEvent) => {\n if (event.response?.status) {\n props.onFileUploadComplete && props.onFileUploadComplete();\n }\n };\n\n // Wait for authentication headers\n if (!authHeaders) {\n return
    Loading...
    ;\n }\n\n return (\n {\n if (reference !== null) {\n reference.querySelector('.k-upload-button > input')!.setAttribute('title', '');\n }\n }}\n >\n \n \n );\n};\n\nexport default BTUpload;\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport React, { useContext, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { BidderFileUpload } from '../../../../../classes/odata/bidder-file-upload';\nimport { BidPackageApi } from '../../../../../services';\nimport { getShortDateString } from '../../../../../utils/dates';\nimport { getFileExtension } from '../../../../../utils/strings';\nimport BTCard from '../../../../common-page-components/card/BTCard';\nimport BTCardsContainer, {\n BTCardListing,\n BTCardsContainerHighlightableText,\n} from '../../../../common-page-components/cards-container/BTCardsContainer';\nimport FormErrorContainer from '../../../../common-page-components/forms/form-error-container/FormErrorContainer';\nimport { LoadingPageOverlayContext } from '../../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\nimport BTUpload from '../../../../common-page-components/upload/BTUpload';\nimport './BidderDocumentsForm.scss';\n\ninterface Props {\n bidderCompanyName: string;\n bidPackageId: string;\n bidderFileUploads: BidderFileUpload[];\n onDeleteDocumentClick: (bidderCompanyName: string, document: BidderFileUpload) => void;\n onDownloadDocumentClick: (bidderCompanyName: string, document: BidderFileUpload) => void;\n isReadOnly: boolean;\n isFrozen: boolean;\n}\n\nconst MaxNumFilesSelected = 5;\n\nconst LinkButton: React.FC<{\n text: string;\n alignment: 'left' | 'right' | 'center';\n onClick: () => void;\n}> = (props) => {\n return (\n \n
    \n
    \n {props.text}\n
    \n
    \n \n );\n};\n\nconst BidderDocumentsForm: React.FC = (props) => {\n const { t } = useTranslation();\n\n const { showPageLoadingOverlay } = useContext(LoadingPageOverlayContext);\n\n const [errorMessage, setErrorMessage] = useState(null);\n\n const validateBeforeFileUpload = (fileNames: string[]): boolean => {\n setErrorMessage(null);\n\n // Check for the max number of files selected\n // NOTE: The request will still be sent despite the error message. This check is also enforced on the server side\n if (fileNames.length > 5) {\n setErrorMessage(\n t('bid-package:bidderDocumentMaxFilesSelected', {\n MaxNumFilesSelected: MaxNumFilesSelected,\n }),\n );\n return false;\n }\n\n // Check for duplicated files\n const existingFileNames = props.bidderFileUploads.map((fu) => fu.fileName);\n\n const duplicatedFileNames = fileNames.filter((fileName) =>\n existingFileNames.includes(fileName),\n );\n const duplicatedFileNameString = duplicatedFileNames.join(', ');\n\n if (duplicatedFileNames.length !== 0) {\n setErrorMessage(\n t('bid-package:bidderDocumentDuplicateFiles', { fileNames: duplicatedFileNameString }),\n );\n }\n\n return duplicatedFileNames.length === 0;\n };\n\n const getCardIcon = (filename: string): JSX.Element => {\n const fileExt = getFileExtension(filename);\n switch (fileExt) {\n case 'pdf':\n return ;\n\n case 'doc':\n case 'docx':\n return ;\n\n case 'xlxs':\n case 'csv':\n return ;\n\n case 'jpg':\n case 'jpeg':\n case 'png':\n case 'tiff':\n return ;\n\n default:\n return ;\n }\n };\n\n const generateBTCardListings = (): BTCardListing[] => {\n return props.bidderFileUploads.map(\n (doc): BTCardListing => {\n const formattedUploadDate = getShortDateString(doc.uploadDate!);\n\n return {\n searchData: [doc.fileName!, formattedUploadDate],\n sortValue: doc.fileName!,\n cardJSX: (\n \n
    \n \n
    \n
    {getCardIcon(doc.fileName!)}
    \n
    \n \n
    \n
    \n
    \n {props.isFrozen ? (\n <>\n ) : (\n props.onDownloadDocumentClick(props.bidderCompanyName, doc)}\n />\n )}\n {props.isReadOnly ? (\n <>\n ) : (\n props.onDeleteDocumentClick(props.bidderCompanyName, doc)}\n />\n )}\n
    \n
    \n
    \n ),\n };\n },\n );\n };\n\n return (\n
    \n {props.isReadOnly ? (\n <>\n ) : (\n
    \n

    {t('bid-package:uploadDocuments')}

    \n {\n if (validateBeforeFileUpload(fileNames)) {\n // Handle showing the loading overlay here, only if we pass validation,\n // so the overlay shows prior to the upload process.\n // Hiding of the overlay will happen elsewhere (the bid package page),\n // once the upload completes.\n showPageLoadingOverlay();\n }\n }}\n additionalFormData={{\n bidPackageId: props.bidPackageId,\n bidderCompanyName: props.bidderCompanyName,\n }}\n />\n
    \n )}\n {errorMessage && }\n\n

    {t('bid-package:bidderDocuments')}

    \n
    \n \n
    \n
    \n );\n};\n\nexport default BidderDocumentsForm;\n","import FileSaver from 'file-saver';\r\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { DeleteBidPackageBidderDocumentCommand } from '../../../../../classes/commands/bid-packages/delete-bid-package-bidder-document-command';\r\nimport { BidderFileUpload } from '../../../../../classes/odata/bidder-file-upload';\r\nimport { BidPackageApi } from '../../../../../services';\r\nimport { useLogger } from '../../../../../services/logger/Logger';\r\nimport { NotificationService } from '../../../../../services/notification/notification-service';\r\nimport { QueryHttpService } from '../../../../../services/query/query-http-service';\r\nimport { ConfirmationOverlayContext } from '../../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport FrozenEntityNotification from '../../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\r\nimport { LoadingPageOverlayContext } from '../../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport BTModal from '../../../../common-page-components/modal/BTModal';\r\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport useCommandServiceHelper from '../../../../shared-page-components/hooks/useCommandServiceHelper';\r\nimport BidderDocumentsForm from '../components/BidderDocumentsForm';\r\n\r\nexport interface Props {\r\n projectId: string;\r\n bidPackageId: string;\r\n bidderCompanyName: string;\r\n bidderFileUploadsContainerId: string | undefined;\r\n modalIsOpen: boolean;\r\n onModalClose: () => void;\r\n isReadOnly: boolean;\r\n isFrozen: boolean;\r\n}\r\n\r\nconst BidderDocumentsModal: React.FC = (props) => {\r\n const { t } = useTranslation();\r\n const logger = useLogger();\r\n\r\n const { executeCommand } = useCommandServiceHelper();\r\n\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n\r\n const { showErrorNotification } = useContext(NotificationPanelContext);\r\n\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n\r\n const {\r\n projectId,\r\n bidPackageId,\r\n bidderCompanyName,\r\n bidderFileUploadsContainerId: sourceId,\r\n } = props;\r\n\r\n const previousSourceId = useRef();\r\n\r\n const [bidderFileUploads, setBidderFileUploads] = useState();\r\n\r\n const isDataLoaded = useRef(false);\r\n\r\n // Function that will load BidderFileUploads from the bidpackage api\r\n const loadBidderFileUploads = useCallback(async () => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n const bidderFileUploadsResults = await BidPackageApi.getBidderFileUploadsByBidPackageIdAndCompanyName(\r\n bidPackageId,\r\n bidderCompanyName,\r\n );\r\n\r\n if (!bidderFileUploadsResults) {\r\n return;\r\n }\r\n\r\n setBidderFileUploads(bidderFileUploadsResults);\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('bid-package:loadBidderDocumentsError'));\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n }, [\r\n bidPackageId,\r\n bidderCompanyName,\r\n showPageLoadingOverlay,\r\n logger,\r\n showErrorNotification,\r\n t,\r\n hidePageLoadingOverlay,\r\n ]);\r\n\r\n // Initial data load\r\n useEffect(() => {\r\n if (!isDataLoaded.current) {\r\n loadBidderFileUploads();\r\n isDataLoaded.current = true;\r\n }\r\n }, [loadBidderFileUploads]);\r\n\r\n // Respond to all events notifications\r\n useEffect(() => {\r\n if (!sourceId) {\r\n return;\r\n }\r\n\r\n // If the source ID changed and it went from a falsey value to a truthy one,\r\n // we want to manually load the file uploads since the code below would not have received a SignalR notification\r\n // for the new file upload container ID (but will going forward)\r\n if (sourceId !== previousSourceId.current) {\r\n if (!previousSourceId.current && sourceId) {\r\n loadBidderFileUploads();\r\n }\r\n\r\n previousSourceId.current = sourceId;\r\n }\r\n\r\n NotificationService.onAllEventsForCommandProcessed((message) => {\r\n // If there is no file upload container, there's nothing to change\r\n if (!sourceId) {\r\n return;\r\n }\r\n\r\n // Ignore messages for other entities\r\n if (!message.SourceIds.includes(sourceId)) {\r\n return;\r\n }\r\n\r\n hidePageLoadingOverlay(true);\r\n\r\n // something happened pertaining to our sourceId, so reload the bidderfileuploads from source.\r\n loadBidderFileUploads();\r\n });\r\n\r\n return function cleanup() {\r\n NotificationService.offAllEventsForCommandProcessed();\r\n };\r\n }, [hidePageLoadingOverlay, loadBidderFileUploads, sourceId]);\r\n\r\n const deleteBidderDocument = async (\r\n bidPackageId: string,\r\n bidderCompanyName: string,\r\n document: BidderFileUpload,\r\n ) => {\r\n showConfirmationOverlay({\r\n text: t('bid-package:confirmDeleteBidderDocument', { docName: document.fileName }),\r\n buttons: [\r\n {\r\n text: t('general:yes'),\r\n onClick: async (): Promise => {\r\n hideConfirmationOverlay();\r\n\r\n const command = new DeleteBidPackageBidderDocumentCommand(\r\n bidPackageId,\r\n bidderCompanyName,\r\n document.fileName || '',\r\n );\r\n\r\n await executeCommand({\r\n commandToExecute: command,\r\n commandExecutionType: 'relies-on-signal-r-for-completion',\r\n customErrorMessage: t('bid-package:deleteBidderDocumentsError'),\r\n commandSuccessCallback: loadBidderFileUploads,\r\n commandTimeoutFunction: loadBidderFileUploads,\r\n });\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:no'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n };\r\n\r\n const downloadBidderDocument = async (\r\n projectId: string,\r\n bidPackageId: string,\r\n bidderCompanyName: string,\r\n bidderDoc: BidderFileUpload,\r\n ) => {\r\n const downloadUrl = BidPackageApi.getBidderDocumentDownloadUrl(\r\n projectId,\r\n bidPackageId,\r\n bidderCompanyName,\r\n bidderDoc.fileName!,\r\n );\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n const service = await QueryHttpService.getQueryService();\r\n const response = await service.get(downloadUrl, { responseType: 'blob' });\r\n FileSaver.saveAs(response.data, bidderDoc.fileName!);\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('bid-package:downloadBidderDocumentsError'));\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n {!bidderFileUploads ? (\r\n <>\r\n ) : (\r\n \r\n {props.isFrozen ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n {\r\n deleteBidderDocument(bidPackageId, bidderCompanyName, document);\r\n }}\r\n onDownloadDocumentClick={async (\r\n bidderCompanyName: string,\r\n document: BidderFileUpload,\r\n ) => {\r\n downloadBidderDocument(projectId, bidPackageId, bidderCompanyName, document);\r\n }}\r\n isReadOnly={props.isReadOnly || props.isFrozen}\r\n isFrozen={props.isFrozen}\r\n />\r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\nexport default BidderDocumentsModal;\r\n","import React, { useCallback, useState } from 'react';\r\nimport BidderDocumentsModal from '../components/BidderDocumentsModal';\r\n\r\ninterface ReturnValue {\r\n showBidderDocumentsModal: () => void;\r\n getBidderDocumentsModalJSX: (\r\n projectId: string,\r\n bidPackageId: string,\r\n bidderCompanyName: string,\r\n bidderFileUploadsContainerId: string | undefined,\r\n onModalClose: () => void,\r\n isReadOnly: boolean,\r\n isFrozen: boolean,\r\n ) => JSX.Element;\r\n}\r\n\r\nconst useBidPackageBidders_DocumentsModal = (): ReturnValue => {\r\n const [modalIsOpen, setModalIsOpen] = useState(false);\r\n\r\n const showBidderDocumentsModal = useCallback(() => {\r\n setModalIsOpen(true);\r\n }, []);\r\n\r\n const getBidderDocumentsModalJSX = (\r\n projectId: string,\r\n bidPackageId: string,\r\n bidderCompanyName: string,\r\n bidderFileUploadsContainerId: string | undefined,\r\n onModalClose: () => void,\r\n isReadOnly: boolean,\r\n isFrozen: boolean,\r\n ): JSX.Element => {\r\n return (\r\n {\r\n setModalIsOpen(false);\r\n onModalClose();\r\n }}\r\n isReadOnly={isReadOnly}\r\n isFrozen={isFrozen}\r\n />\r\n );\r\n };\r\n\r\n return {\r\n showBidderDocumentsModal,\r\n getBidderDocumentsModalJSX,\r\n };\r\n};\r\n\r\nexport default useBidPackageBidders_DocumentsModal;\r\n","import React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Bidder } from '../../../../../classes/odata/bidder';\r\nimport './BidderInfoModal.scss';\r\n\r\ninterface Props {\r\n bidder: Bidder;\r\n}\r\n\r\nconst BidderInfoModal: React.FC = (props) => {\r\n const { t } = useTranslation();\r\n\r\n return (\r\n
    \r\n

    {props.bidder.companyName}

    \r\n\r\n
    \r\n

    Contact Info

    \r\n
    \r\n
    \r\n \r\n
    {props.bidder.primaryContactName || 'N/A'}
    \r\n
    \r\n\r\n
    \r\n \r\n
    {props.bidder.primaryContactEmail || 'N/A'}
    \r\n
    \r\n\r\n
    \r\n \r\n
    {props.bidder.phoneNumber || 'N/A'}
    \r\n
    \r\n\r\n
    \r\n \r\n
    {props.bidder.faxNumber || 'N/A'}
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n );\r\n};\r\n\r\nexport default BidderInfoModal;\r\n","import React, { useCallback, useState } from 'react';\nimport { Bidder } from '../../../../../classes/odata/bidder';\nimport BTModal from '../../../../common-page-components/modal/BTModal';\nimport BidderInfoModal from '../components/BidderInfoModal';\n\ninterface ReturnValue {\n showBidderInfo: (bidder: Bidder) => void;\n getBidderInfoJSX: () => JSX.Element;\n}\n\ninterface ModalState {\n isOpen: boolean;\n bidder: Bidder | null;\n}\n\nconst useBidPackageBidders_InfoModal = (): ReturnValue => {\n const [modalState, setModalState] = useState({\n isOpen: false,\n bidder: null,\n });\n\n const showBidderInfo = useCallback((bidder: Bidder) => {\n setModalState({ bidder: bidder, isOpen: true });\n }, []);\n\n const onBidderInfoModalClose = useCallback(() => {\n setModalState((curr) => ({ ...curr, isOpen: false }));\n }, [setModalState]);\n\n const getBidderInfoJSX = useCallback((): JSX.Element => {\n return modalState.bidder ? (\n \n \n \n ) : (\n <>\n );\n }, [modalState.bidder, modalState.isOpen, onBidderInfoModalClose]);\n\n return {\n getBidderInfoJSX,\n showBidderInfo,\n };\n};\n\nexport default useBidPackageBidders_InfoModal;\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class AddEditBidderNotesToBidPackageCommand extends CommandBase {\r\n constructor(\r\n public bidPackageId: string,\r\n public bidderNotesId: string | null,\r\n public companyName: string,\r\n public text: string,\r\n ) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.AddEditBidderNotes',\r\n '/bid-package/add-bidder-notes',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { clone } from 'lodash';\nimport React, { useCallback, useContext, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AddEditBidderNotesToBidPackageCommand } from '../../../../../classes/commands/bid-packages/add-edit-bidder-notes-to-bid-package-command';\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\nimport { LoadingPageOverlayContext } from '../../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\nimport { Bidder } from '../../../../../classes/odata/bidder';\nimport { CommandManagerService } from '../../../../../services/command/command-manager-service';\nimport { useLogger } from '../../../../../services/logger/Logger';\nimport { ConfirmationOverlayContext } from '../../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport BTModal from '../../../../common-page-components/modal/BTModal';\nimport BTNotes from '../../../../common-page-components/notes/BTNotes';\n\ninterface ReturnValue {\n editBidderNotes: (bidder: Bidder) => void;\n getBidderNotesJSX: (isReadOnly: boolean, isFrozen: boolean) => JSX.Element;\n}\n\ninterface ModalState {\n isOpen: boolean;\n bidderToEdit: Bidder | null;\n}\n\nconst useBidPackageBidders_Notes = (\n onBidderNotesChangeCallback: (bidder: Bidder) => void,\n): ReturnValue => {\n const { t } = useTranslation();\n const logger = useLogger();\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\n const { showSuccessNotification, showErrorNotification } = useContext(NotificationPanelContext);\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n\n const [modalState, setModalState] = useState({\n isOpen: false,\n bidderToEdit: null,\n });\n\n const editBidderNotes = useCallback(\n (bidder: Bidder) => {\n const bidderToEdit = clone(bidder);\n bidderToEdit.notes = bidderToEdit.notes || '';\n setModalState({ isOpen: true, bidderToEdit: bidderToEdit });\n },\n [setModalState],\n );\n\n const closeBidderNotesModal = useCallback(() => {\n setModalState((curr) => ({ ...curr, isOpen: false }));\n }, [setModalState]);\n\n const onBidderNotesChange = useCallback(\n async (newNotes: string): Promise => {\n try {\n if (!modalState.bidderToEdit) {\n return;\n }\n\n if (\n !modalState.bidderToEdit.bidPackageId ||\n !modalState.bidderToEdit.companyName ||\n modalState.bidderToEdit.notesId === undefined\n ) {\n return;\n }\n\n showPageLoadingOverlay();\n\n newNotes = newNotes.trim();\n const response = await CommandManagerService.executeCommand(\n new AddEditBidderNotesToBidPackageCommand(\n modalState.bidderToEdit.bidPackageId,\n modalState.bidderToEdit.notesId,\n modalState.bidderToEdit.companyName,\n newNotes.trim(),\n ),\n );\n\n if (!response) {\n throw Error(t('bid-package:errorAddNotes'));\n }\n\n closeBidderNotesModal();\n\n const bidderCopy = clone(modalState.bidderToEdit);\n bidderCopy.notes = newNotes;\n bidderCopy.notesId = response.data;\n\n onBidderNotesChangeCallback(bidderCopy);\n\n showSuccessNotification(t('general:success'), t('bid-package:successSetNotes'));\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('bid-package:errorAddNotes'));\n } finally {\n hidePageLoadingOverlay();\n }\n },\n [\n modalState.bidderToEdit,\n showPageLoadingOverlay,\n closeBidderNotesModal,\n onBidderNotesChangeCallback,\n showSuccessNotification,\n t,\n showErrorNotification,\n hidePageLoadingOverlay,\n logger,\n ],\n );\n\n const onBidderNotesDiscard = useCallback(\n (notes: string): void => {\n if (!modalState.bidderToEdit) {\n return;\n }\n\n if (notes.trim() === modalState.bidderToEdit.notes!.trim()) {\n closeBidderNotesModal();\n return;\n }\n\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: (): void => {\n hideConfirmationOverlay();\n closeBidderNotesModal();\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n },\n [\n modalState.bidderToEdit,\n showConfirmationOverlay,\n t,\n closeBidderNotesModal,\n hideConfirmationOverlay,\n ],\n );\n\n const getBidderNotesJSX = useCallback(\n (isReadOnly: boolean, isFrozen: boolean): JSX.Element => {\n return modalState.bidderToEdit ? (\n \n \n \n ) : (\n <>\n );\n },\n [\n modalState.bidderToEdit,\n modalState.isOpen,\n closeBidderNotesModal,\n t,\n onBidderNotesChange,\n onBidderNotesDiscard,\n ],\n );\n\n return {\n editBidderNotes,\n getBidderNotesJSX,\n };\n};\n\nexport default useBidPackageBidders_Notes;\n","// NOTE: This file is a TSX file because we reference JSX elements\r\nimport React from 'react';\r\n\r\nconst generateEmptyGridRow = (\r\n isPrimaryGridRow: boolean,\r\n rowId: string,\r\n): BTGridRowPrimary | BTGridRowBase => {\r\n const returnValue: BTGridRowBase = {\r\n cells: [],\r\n id: rowId,\r\n isPrimaryGridRow: isPrimaryGridRow,\r\n showBottomBorder: false,\r\n };\r\n\r\n if (isPrimaryGridRow) {\r\n const returnValue2: BTGridRowPrimary = {\r\n groupingLevel: null,\r\n isCollapsibleTrigger: false,\r\n collapseDirection: null,\r\n isHoverable: false,\r\n isSelectable: false,\r\n ...returnValue,\r\n };\r\n\r\n return returnValue2;\r\n }\r\n\r\n return returnValue;\r\n};\r\n\r\nconst generateEmptyGridRow_Primary = (rowId: string): BTGridRowPrimary => {\r\n return generateEmptyGridRow(true, rowId) as BTGridRowPrimary;\r\n};\r\n\r\nconst generateEmptyGridRow_Base = (rowId: string): BTGridRowBase => {\r\n return generateEmptyGridRow(false, rowId) as BTGridRowBase;\r\n};\r\n\r\nconst generateEmptyGridRowWithEmptyCells = (\r\n isPrimaryGridRow: boolean,\r\n rowId: string,\r\n gridCellsToCreate: number,\r\n gridCellsWidth: BTGridCellWidths,\r\n): BTGridRowPrimary | BTGridRowBase => {\r\n const returnValue: BTGridRowBase = generateEmptyGridRow(isPrimaryGridRow, rowId);\r\n\r\n for (let i = 0; i < gridCellsToCreate; i++) {\r\n returnValue.cells.push({\r\n cellContent:
     
    ,\r\n cellWidth: gridCellsWidth,\r\n });\r\n }\r\n\r\n return returnValue;\r\n};\r\n\r\nconst generateEmptyGridRowWithEmptyCells_Primary = (\r\n rowId: string,\r\n gridCellsToCreate: number,\r\n gridCellsWidth: BTGridCellWidths,\r\n): BTGridRowPrimary => {\r\n return generateEmptyGridRowWithEmptyCells(\r\n true,\r\n rowId,\r\n gridCellsToCreate,\r\n gridCellsWidth,\r\n ) as BTGridRowPrimary;\r\n};\r\n\r\nconst generateEmptyGridRowWithNoCells_Base = (rowId: string): BTGridRowBase => {\r\n return generateEmptyGridRow(false, rowId) as BTGridRowBase;\r\n};\r\n\r\nconst generateEmptyGridRowWithNoCells_Primary = (rowId: string): BTGridRowPrimary => {\r\n return generateEmptyGridRow(true, rowId) as BTGridRowPrimary;\r\n};\r\n\r\nconst generateEmptyGridRowWithEmptyCells_Base = (\r\n rowId: string,\r\n gridCellsToCreate: number,\r\n gridCellsWidth: BTGridCellWidths,\r\n): BTGridRowBase => {\r\n return generateEmptyGridRowWithEmptyCells(\r\n false,\r\n rowId,\r\n gridCellsToCreate,\r\n gridCellsWidth,\r\n ) as BTGridRowBase;\r\n};\r\n\r\nconst generateGridRow_Grouped = (data: {\r\n id: string;\r\n isReadOnly: boolean;\r\n lineItem: BTGridGroupedRow;\r\n sortableInfo?: BTGridRowSortableInfo;\r\n groupingLevel: number | null;\r\n order: number | null;\r\n groupingKey1: string | null;\r\n groupingKey2: string | null;\r\n groupingParent1Info?: BTGridRowGroupingParentInfo;\r\n groupingParent2Info?: BTGridRowGroupingParentInfo;\r\n globalCollapseResponseKey: string | null;\r\n}): BTGridRowPrimary => {\r\n const newRowObj: BTGridRowPrimary = {\r\n id: data.id,\r\n isPrimaryGridRow: true,\r\n cells: [],\r\n groupingLevel: data.groupingLevel,\r\n isCollapsibleTrigger: true,\r\n collapseDirection: 'down',\r\n isHoverable: true,\r\n isSelectable: true,\r\n sortableInfo: data.sortableInfo,\r\n groupingInfo: {\r\n isGroupedRow: true,\r\n order: data.order,\r\n groupingLevel: data.lineItem.groupingLevel,\r\n groupingKey1: data.groupingKey1,\r\n groupingKey2: data.groupingKey2,\r\n groupingParent1Info: data.groupingParent1Info,\r\n groupingParent2Info: data.groupingParent2Info,\r\n globalCollapseResponseKey: data.globalCollapseResponseKey,\r\n globalCollapseTriggerKey: null,\r\n },\r\n };\r\n\r\n newRowObj.cells.push({\r\n cellWidth: 'xl',\r\n cellContent:
    {data.lineItem.groupingKey}
    ,\r\n });\r\n\r\n newRowObj.cells.push({\r\n cellWidth: 'fill',\r\n cellContent:
    ,\r\n });\r\n\r\n return newRowObj;\r\n};\r\n\r\nexport {\r\n generateEmptyGridRow_Base,\r\n generateEmptyGridRow_Primary,\r\n generateEmptyGridRowWithEmptyCells_Base,\r\n generateEmptyGridRowWithEmptyCells_Primary,\r\n generateEmptyGridRowWithNoCells_Base,\r\n generateEmptyGridRowWithNoCells_Primary,\r\n generateGridRow_Grouped,\r\n};\r\n","import React from 'react';\r\nimport { Observable } from 'rxjs';\r\nimport { useObservableWithValue } from '../../../hooks/observables/useObservable';\r\n\r\nexport interface BTPopoverInfo {\r\n element: HTMLElement; // A reference to the HTML element that triggered the popover, for positioning purposes\r\n title: string;\r\n text: string;\r\n placement: 'bottom' | 'top' | 'left' | 'right';\r\n showCloseButton: boolean;\r\n}\r\n\r\ninterface BTPopoverContextInterface {\r\n displayedPopoverInfo$: Observable;\r\n setDisplayedPopoverInfo: (newValue: BTPopoverInfo | null) => void;\r\n}\r\n\r\nconst BTPopoverContext = React.createContext(\r\n {} as BTPopoverContextInterface,\r\n);\r\n\r\nconst BTPopoverContextProvider: React.FC = ({ children }) => {\r\n const [\r\n displayedPopoverInfo$,\r\n setDisplayedPopoverInfo,\r\n ] = useObservableWithValue();\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nexport { BTPopoverContext, BTPopoverContextProvider };\r\n","import React, { useCallback, useRef } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport GeneralConstants from '../../../../../../constants/general';\r\nimport EntityValidationConstants from '../../../../../../constants/general/entity-validation-constants';\r\nimport { normalizeNullOrUndefined } from '../../../../../../utils/general';\r\nimport { removeNonNumericCharsFromString } from '../../../../../../utils/strings';\r\nimport BTNumericInput from '../../../../../common-page-components/inputs/BTNumericInput';\r\nimport { BidClassificationTypes } from '../../../../../enums/bid-package-enums';\r\n\r\ntype BidValueInputTypes = 'text' | 'number' | 'number-5' | 'checkbox' | 'combo';\r\n\r\nexport interface GetInputElementForBidFieldParameter {\r\n inputType: BidValueInputTypes;\r\n isLineItem: boolean;\r\n price?: number | null;\r\n value?: string | boolean | null;\r\n classification?: number;\r\n placeholder?: string;\r\n onBidFocusCallback?: () => void;\r\n onBidChangeCallback?: (bidderValue: BidderValue) => void;\r\n onBidBlurCallback?: (bidderValue: BidderValue) => void;\r\n // The keyboard events are only applicable for \"number\" inputs\r\n allowedNonNumericKeys?: string[];\r\n onKeyDownCallback?: (e: KeyboardEvent) => void;\r\n isDisabled: boolean;\r\n}\r\n\r\ninterface ReturnValue {\r\n getInputElementForBidField: (data: GetInputElementForBidFieldParameter) => JSX.Element;\r\n}\r\n\r\ninterface BidClassificationOption {\r\n id: number;\r\n name: string;\r\n tooltipName: string;\r\n}\r\n\r\nconst useBidderHelpers = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const getInputElementForBidField = useCallback(\r\n ({\r\n inputType,\r\n isLineItem,\r\n price,\r\n value,\r\n classification,\r\n placeholder,\r\n onBidChangeCallback,\r\n onBidBlurCallback,\r\n onBidFocusCallback,\r\n allowedNonNumericKeys,\r\n onKeyDownCallback,\r\n isDisabled,\r\n }: GetInputElementForBidFieldParameter): JSX.Element => {\r\n const bidClassificationOptions: BidClassificationOption[] = [\r\n {\r\n id: BidClassificationTypes.Unallocated,\r\n name: ' ',\r\n tooltipName: t('bid-package:bidClassificationType_Unallocated'),\r\n },\r\n {\r\n id: BidClassificationTypes.GeneralRequirement,\r\n name: GeneralConstants.KEY_G,\r\n tooltipName: t('bid-package:bidClassificationType_GeneralRequirements'),\r\n },\r\n {\r\n id: BidClassificationTypes.Included,\r\n name: GeneralConstants.KEY_I,\r\n tooltipName: t('bid-package:bidClassificationType_Included'),\r\n },\r\n {\r\n id: BidClassificationTypes.MissingScope,\r\n name: GeneralConstants.KEY_M,\r\n tooltipName: t('bid-package:bidClassificationType_MissingScope'),\r\n },\r\n {\r\n id: BidClassificationTypes.OwnerAllow,\r\n name: GeneralConstants.KEY_O,\r\n tooltipName: t('bid-package:bidClassificationType_OwnerAllow'),\r\n },\r\n {\r\n id: BidClassificationTypes.Risk,\r\n name: GeneralConstants.KEY_R,\r\n tooltipName: t('bid-package:bidClassificationType_RiskManagement'),\r\n },\r\n {\r\n id: BidClassificationTypes.SubBid,\r\n name: GeneralConstants.KEY_S,\r\n tooltipName: t('bid-package:bidClassificationType_SubBid'),\r\n },\r\n ];\r\n\r\n // If price is undefined, set it to null\r\n if (price === undefined) {\r\n price = null;\r\n }\r\n\r\n switch (inputType) {\r\n case 'combo':\r\n const matchingEnumKey =\r\n bidClassificationOptions.find((v) => v.id === classification)?.id ??\r\n BidClassificationTypes.Unallocated;\r\n\r\n const getClassificationInputFieldCSSClass = (): string => {\r\n switch (matchingEnumKey) {\r\n case BidClassificationTypes.MissingScope:\r\n return 'light-blue';\r\n\r\n case BidClassificationTypes.Risk:\r\n return 'red';\r\n\r\n default:\r\n return 'none';\r\n }\r\n };\r\n\r\n const valueRequiredClassifications = [\r\n BidClassificationTypes.Unallocated,\r\n BidClassificationTypes.GeneralRequirement,\r\n BidClassificationTypes.OwnerAllow,\r\n BidClassificationTypes.Risk,\r\n BidClassificationTypes.SubBid,\r\n ];\r\n\r\n // A bid is \"unleveled\" when there is no price and no classification (or the classification is the default or requires a value).\r\n // NOTE: This only applies to line items, not requirements or anything else.\r\n const bidIsUnleveled =\r\n isLineItem &&\r\n normalizeNullOrUndefined(price) === null &&\r\n ((classification && valueRequiredClassifications.includes(classification)) ||\r\n normalizeNullOrUndefined(classification) === null);\r\n\r\n const isIncludedBidClassification = matchingEnumKey === BidClassificationTypes.Included;\r\n\r\n const nonNumericKeysToPassThrough: string[] = [\r\n GeneralConstants.KEY_G,\r\n GeneralConstants.KEY_I,\r\n GeneralConstants.KEY_M,\r\n GeneralConstants.KEY_O,\r\n GeneralConstants.KEY_R,\r\n GeneralConstants.KEY_S,\r\n GeneralConstants.KEY_Z,\r\n GeneralConstants.KEY_SPACE,\r\n ];\r\n\r\n return (\r\n
    \r\n
    \r\n {/*\r\n When the classification is \"Included\", the numeric value should be empty. However, we allow the user to enter numeric data, since they may change the classification\r\n to something other than \"Included\" with a hotkey in this input. If they leave \"Included\" selected, we will just blow out their entered data when they blur away\r\n from this field.\r\n */}\r\n\r\n {\r\n if (onKeyDownCallback) {\r\n onKeyDownCallback(e);\r\n }\r\n\r\n // If the user pressed one of the letters associated with a classification, set that classification\r\n let classificationToSet: number | null = null;\r\n let newPrice: number | undefined = price !== null ? price : undefined;\r\n\r\n switch ((e.key || '').toUpperCase()) {\r\n case GeneralConstants.KEY_G:\r\n classificationToSet = BidClassificationTypes.GeneralRequirement;\r\n break;\r\n\r\n case GeneralConstants.KEY_I:\r\n classificationToSet = BidClassificationTypes.Included;\r\n newPrice = undefined;\r\n break;\r\n\r\n case GeneralConstants.KEY_M:\r\n classificationToSet = BidClassificationTypes.MissingScope;\r\n break;\r\n\r\n case GeneralConstants.KEY_O:\r\n classificationToSet = BidClassificationTypes.OwnerAllow;\r\n break;\r\n\r\n case GeneralConstants.KEY_R:\r\n classificationToSet = BidClassificationTypes.Risk;\r\n break;\r\n\r\n case GeneralConstants.KEY_S:\r\n classificationToSet = BidClassificationTypes.SubBid;\r\n break;\r\n\r\n case GeneralConstants.KEY_SPACE:\r\n classificationToSet = BidClassificationTypes.Unallocated;\r\n break;\r\n }\r\n\r\n if (\r\n classificationToSet !== null &&\r\n classificationToSet !== matchingEnumKey &&\r\n onBidChangeCallback\r\n ) {\r\n // NOTE: When we bubble up change events, we blank out the price for \"Included\" bids,\r\n // but if the user changes the classification type several times with the keyboard shortcuts\r\n // without leaving the numeric input, we want to use the value that is currently in the input\r\n // when the classification is changed to something that is not \"Included\".\r\n if (classificationToSet === BidClassificationTypes.Included) {\r\n onBidChangeCallback({\r\n price: undefined,\r\n classification: classificationToSet,\r\n value: undefined,\r\n });\r\n } else {\r\n if (\r\n matchingEnumKey === BidClassificationTypes.Included &&\r\n classificationToSet !== BidClassificationTypes.Included\r\n ) {\r\n const currentInputValue = (e.target as HTMLInputElement).value ?? '0';\r\n\r\n // parse float misbehaves with commas (12,345 => 12), so we need to strip them out.\r\n const inputValueWithNoCommas = removeNonNumericCharsFromString(\r\n currentInputValue,\r\n );\r\n let currentNumericInputValue: number = parseFloat(inputValueWithNoCommas);\r\n\r\n if (isNaN(currentNumericInputValue)) {\r\n currentNumericInputValue = 0;\r\n }\r\n\r\n onBidChangeCallback({\r\n price: currentNumericInputValue ?? undefined,\r\n classification: classificationToSet,\r\n value: undefined,\r\n });\r\n } else {\r\n onBidChangeCallback({\r\n price: newPrice,\r\n classification: classificationToSet,\r\n value: undefined,\r\n });\r\n }\r\n }\r\n }\r\n }}\r\n onFocus={() => {\r\n if (onBidFocusCallback) {\r\n onBidFocusCallback();\r\n }\r\n }}\r\n onChange={(inputElement) => {\r\n if (onBidChangeCallback) {\r\n let newValue: number | null | undefined = inputElement.target.value;\r\n\r\n if (newValue === null) {\r\n newValue = undefined;\r\n }\r\n\r\n onBidChangeCallback({\r\n price: isIncludedBidClassification ? undefined : newValue,\r\n classification: matchingEnumKey ?? BidClassificationTypes.Unallocated,\r\n value: undefined,\r\n });\r\n }\r\n }}\r\n onBlur={(inputElement) => {\r\n if (onBidBlurCallback) {\r\n let newValue: number | null | undefined = inputElement.target.value;\r\n\r\n if (newValue === null) {\r\n newValue = undefined;\r\n }\r\n\r\n onBidBlurCallback({\r\n price: isIncludedBidClassification ? undefined : newValue,\r\n classification: matchingEnumKey ?? BidClassificationTypes.Unallocated,\r\n value: undefined,\r\n });\r\n }\r\n }}\r\n />\r\n
    \r\n\r\n \r\n
    \r\n );\r\n\r\n case 'text':\r\n return (\r\n
    \r\n {isDisabled ? (\r\n value\r\n ) : (\r\n {\r\n if (onBidFocusCallback) {\r\n onBidFocusCallback();\r\n }\r\n }}\r\n onChange={(inputElement) => {\r\n if (onBidChangeCallback) {\r\n let newValue: string | null | undefined = inputElement.target.value;\r\n\r\n if (newValue === null) {\r\n newValue = undefined;\r\n } else if (\r\n newValue.length >\r\n EntityValidationConstants.RequirementFulfillmentEntityLimits.Value_MaxLength\r\n ) {\r\n // We want to prevent the user from entering or pasting a value greater than the DB limit of 500 characters\r\n newValue = newValue.slice(\r\n 0,\r\n EntityValidationConstants.RequirementFulfillmentEntityLimits\r\n .Value_MaxLength,\r\n );\r\n }\r\n\r\n onBidChangeCallback({\r\n value: newValue,\r\n classification: undefined,\r\n price: undefined,\r\n });\r\n }\r\n }}\r\n onBlur={(inputElement) => {\r\n if (onBidBlurCallback) {\r\n const newValue = inputElement.target.value || '';\r\n\r\n onBidBlurCallback({\r\n value: newValue,\r\n classification: undefined,\r\n price: undefined,\r\n });\r\n }\r\n }}\r\n />\r\n )}\r\n
    \r\n );\r\n\r\n case 'number':\r\n case 'number-5':\r\n return (\r\n
    \r\n {\r\n if (onBidFocusCallback) {\r\n onBidFocusCallback();\r\n }\r\n }}\r\n onChange={(inputElement) => {\r\n if (onBidChangeCallback) {\r\n const newValue =\r\n typeof inputElement.target.value === 'number'\r\n ? (inputElement.target.value as number)\r\n : undefined;\r\n\r\n onBidChangeCallback({\r\n price: newValue,\r\n classification: undefined,\r\n value: undefined,\r\n });\r\n }\r\n }}\r\n onBlur={(inputElement) => {\r\n if (onBidBlurCallback) {\r\n let newValue: number | null | undefined = inputElement.target.value;\r\n\r\n if (newValue === null) {\r\n newValue = undefined;\r\n }\r\n\r\n onBidBlurCallback({\r\n price: newValue,\r\n classification: undefined,\r\n value: undefined,\r\n });\r\n }\r\n }}\r\n nonNumericKeysToPassThrough={allowedNonNumericKeys}\r\n allowAnyKeysToPassThrough\r\n onKeyDown={onKeyDownCallback}\r\n />\r\n
    \r\n );\r\n\r\n case 'checkbox':\r\n return (\r\n
    \r\n {\r\n if (onBidFocusCallback) {\r\n onBidFocusCallback();\r\n }\r\n }}\r\n onChange={(inputElement) => {\r\n // NOTE: for checkbox requirement fulfillments, we run the blur callback onChange.\r\n // We don't want the user to have to tab away from the checkbox to commit.\r\n if (onBidChangeCallback && onBidBlurCallback) {\r\n const newValue = inputElement.target.checked;\r\n\r\n onBidChangeCallback({\r\n value: newValue,\r\n price: undefined,\r\n classification: undefined,\r\n });\r\n\r\n // NOTE: We run this in a setTimeout so we can guarantee the react state change tasks\r\n // generated from onBidChangeCallback are handled before onBidBlurCallback\r\n setTimeout(() => {\r\n onBidBlurCallback({\r\n value: newValue,\r\n price: undefined,\r\n classification: undefined,\r\n });\r\n }, 0);\r\n }\r\n }}\r\n />\r\n
    \r\n );\r\n\r\n default:\r\n return <>;\r\n }\r\n },\r\n [t],\r\n );\r\n\r\n return { getInputElementForBidField };\r\n};\r\n\r\ninterface BidderSelectElementProps {\r\n price?: number | null;\r\n isDisabled: boolean;\r\n matchingEnumKey: number;\r\n bidClassificationOptions: BidClassificationOption[];\r\n onBidFocusCallback?: () => void;\r\n onBidChangeCallback?: (bidderValue: BidderValue) => void;\r\n onBidBlurCallback?: (bidderValue: BidderValue) => void;\r\n}\r\n\r\n// NOTE: This is its own component so we can have some extra functionality (like maintaining the last price entered\r\n// when the user toggles between options and gets to \"I\", which blanks out the price).\r\nconst BidderSelectElement: React.FC = ({\r\n price,\r\n isDisabled,\r\n matchingEnumKey,\r\n bidClassificationOptions,\r\n onBidFocusCallback,\r\n onBidChangeCallback,\r\n onBidBlurCallback,\r\n}) => {\r\n const previousPrice = useRef(price ?? null);\r\n\r\n return (\r\n {\r\n let newValueToSet: number | null = null;\r\n\r\n // NOTE: We explicitly listen for certain key presses on this input element so we can\r\n // programmatically change the value -- otherwise the select input will listen for keydown events\r\n // and try to select the item it thinks we want, but this approach is immediate and more reliable.\r\n switch (e.key.toUpperCase()) {\r\n // NOTE: There is no hotkey for the empty select option\r\n\r\n case GeneralConstants.KEY_G:\r\n newValueToSet = BidClassificationTypes.GeneralRequirement;\r\n break;\r\n\r\n case GeneralConstants.KEY_I:\r\n newValueToSet = BidClassificationTypes.Included;\r\n break;\r\n\r\n case GeneralConstants.KEY_M:\r\n newValueToSet = BidClassificationTypes.MissingScope;\r\n break;\r\n\r\n case GeneralConstants.KEY_O:\r\n newValueToSet = BidClassificationTypes.OwnerAllow;\r\n break;\r\n\r\n case GeneralConstants.KEY_R:\r\n newValueToSet = BidClassificationTypes.Risk;\r\n break;\r\n\r\n case GeneralConstants.KEY_S:\r\n newValueToSet = BidClassificationTypes.SubBid;\r\n break;\r\n\r\n default:\r\n return;\r\n }\r\n\r\n if (newValueToSet !== null) {\r\n // Set the new value of the select element\r\n (e.target as HTMLSelectElement).value = newValueToSet?.toString() || '';\r\n\r\n // Raise a change event so the onChange handler runs and updates the state\r\n e.target.dispatchEvent(\r\n new Event('change', {\r\n ...e,\r\n }),\r\n );\r\n\r\n // Prevent the event from bubbling up\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }\r\n }}\r\n onFocus={() => {\r\n if (onBidFocusCallback) {\r\n onBidFocusCallback();\r\n }\r\n }}\r\n onChange={(inputElement) => {\r\n if (onBidChangeCallback) {\r\n const newValue = parseInt(inputElement.target.value);\r\n\r\n if (newValue === BidClassificationTypes.Included) {\r\n // If we're changing to \"Included\", make note of the current value before we blank it out\r\n previousPrice.current = price ?? null;\r\n\r\n onBidChangeCallback({\r\n classification: newValue,\r\n price: undefined,\r\n value: undefined,\r\n });\r\n } else {\r\n onBidChangeCallback({\r\n classification: newValue,\r\n // Try to set the previous price if it's set\r\n price: previousPrice.current ?? price ?? undefined,\r\n value: undefined,\r\n });\r\n }\r\n }\r\n }}\r\n onBlur={(inputElement) => {\r\n if (onBidBlurCallback) {\r\n previousPrice.current = null;\r\n\r\n // NOTE: The selected value will come in as a string\r\n const newValue = inputElement.target.value?.length\r\n ? parseInt(inputElement.target.value)\r\n : null;\r\n\r\n onBidBlurCallback({\r\n price: newValue === BidClassificationTypes.Included ? undefined : price ?? undefined,\r\n classification: newValue ?? BidClassificationTypes.Unallocated,\r\n value: undefined,\r\n });\r\n }\r\n }}\r\n >\r\n {bidClassificationOptions.map((v) => {\r\n return (\r\n \r\n );\r\n })}\r\n \r\n );\r\n};\r\n\r\nexport default useBidderHelpers;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport Big from 'big.js';\r\nimport React, { useCallback, useContext, useRef } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Alternate } from '../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\r\nimport { BidPackageLineItem } from '../../../../../classes/odata/bid-package-line-item';\r\nimport GeneralConstants from '../../../../../constants/general';\r\nimport { generateEmptyGridRowWithNoCells_Primary } from '../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n normalizeNullOrUndefined,\r\n} from '../../../../../utils/general';\r\nimport BTContextMenu from '../../../../common-page-components/context-menu/BTContextMenu';\r\nimport { BTPopoverContext } from '../../../../common-page-components/popover/BTPopoverContext';\r\nimport {\r\n BidClassificationTypes,\r\n RequirementFulfillmentTypes,\r\n} from '../../../../enums/bid-package-enums';\r\nimport useBidPackagePageContext from '../BidPackagePageContext';\r\nimport useBidderHelpers from './helpers/useBidderHelpers';\r\n\r\ninterface GenerateBidPackage_Adjustments_GridSection_Params {\r\n allowEntryInAdjustmentsRow: boolean;\r\n isReadOnly: boolean;\r\n alternate: Alternate | null;\r\n bidPackage: BidPackage | undefined;\r\n collapseShouldIncludeAdjustmentsHeaderRow: boolean;\r\n gridSectionId: string;\r\n isBidPackageTotalsSection: boolean;\r\n projectAlternates: Alternate[];\r\n showTopBorders: boolean;\r\n totalsTitle: string;\r\n globalCollapseResponseKey: string | null;\r\n}\r\n\r\ninterface ReturnValue {\r\n generateBidPackage_Adjustments_GridSection: (\r\n data: GenerateBidPackage_Adjustments_GridSection_Params,\r\n ) => BTGridSection | null;\r\n}\r\n\r\nconst collapsibleIconJSXElementFactory = (element: JSX.Element): JSX.Element =>

    {element}

    ;\r\n\r\nconst getCellbackgroundColorForBidClassificationType = (\r\n bidClassificationType: BidClassificationTypes,\r\n): BTGridCellBackgroundColors => {\r\n switch (bidClassificationType) {\r\n case BidClassificationTypes.GeneralRequirement:\r\n return 'orange';\r\n\r\n case BidClassificationTypes.OwnerAllow:\r\n return 'yellow';\r\n\r\n case BidClassificationTypes.Unallocated:\r\n return 'light-gray';\r\n\r\n case BidClassificationTypes.Risk:\r\n return 'manly-salmon';\r\n\r\n case BidClassificationTypes.MissingScope:\r\n return 'light-blue';\r\n\r\n case BidClassificationTypes.SubBid:\r\n return 'gray';\r\n\r\n default:\r\n return 'none';\r\n }\r\n};\r\n\r\nconst useBidPackageGrid_Adjustments = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const { adjustment_OpenNote, adjustment_Change, adjustment_Blur } = useBidPackagePageContext();\r\n\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const { getInputElementForBidField } = useBidderHelpers();\r\n\r\n // NOTE: These are hard coded currently, but may become database driven in the future\r\n const bidClassificationTypes = useRef<{ id: number; name: string }[]>([\r\n {\r\n id: BidClassificationTypes.Unallocated,\r\n name: t('bid-package:bidClassificationType_Unallocated'),\r\n },\r\n {\r\n id: BidClassificationTypes.GeneralRequirement,\r\n name: t('bid-package:bidClassificationType_GeneralRequirements'),\r\n },\r\n {\r\n id: BidClassificationTypes.MissingScope,\r\n name: t('bid-package:bidClassificationType_MissingScope'),\r\n },\r\n {\r\n id: BidClassificationTypes.OwnerAllow,\r\n name: t('bid-package:bidClassificationType_OwnerAllow'),\r\n },\r\n {\r\n id: BidClassificationTypes.Risk,\r\n name: t('bid-package:bidClassificationType_RiskManagement'),\r\n },\r\n {\r\n id: BidClassificationTypes.SubBid,\r\n name: t('bid-package:bidClassificationType_SubBid'),\r\n },\r\n ]);\r\n\r\n const generateSubGrid_AdjustmentsAndBidClassifications = useCallback(\r\n (data: {\r\n bidPackage: BidPackage;\r\n projectAlternates: Alternate[];\r\n isBidPackageTotalsSection: boolean;\r\n gridSectionId: string;\r\n gridSectionTestId: string;\r\n alternate: Alternate | null;\r\n totalsTitle: string;\r\n showTopBorders: boolean;\r\n collapseShouldIncludeAdjustmentsHeaderRow: boolean;\r\n globalCollapseResponseKey: string | null;\r\n }): BTSubGrid => {\r\n const rows: BTGridRowPrimary[] = [];\r\n\r\n // NOTE: We do NOT show adjustment or classification rows for general condition bid packages\r\n if (!data.bidPackage.isGeneralCondition) {\r\n rows.push({\r\n ...generateEmptyGridRowWithNoCells_Primary(\r\n `${data.gridSectionId} - 06719197-b5a6-4228-8659-0b87b57797fb`,\r\n ),\r\n showBottomBorder: false,\r\n cells: [\r\n {\r\n cellContent: (\r\n
    \r\n {data.isBidPackageTotalsSection ? (\r\n t('bid-package:adjustments')\r\n ) : (\r\n

    {t('bid-package:adjustments')}

    \r\n )}\r\n
    \r\n ),\r\n cellWidth: 'fill',\r\n cellBackgroundColor: 'green',\r\n cellAdditionalStyles: ['border-sides'],\r\n },\r\n ],\r\n groupingInfo: data.collapseShouldIncludeAdjustmentsHeaderRow\r\n ? {\r\n isGroupedRow: false,\r\n order: null,\r\n groupingLevel: null,\r\n groupingKey1: 'Adjustment Rows',\r\n groupingKey2: 'Classification',\r\n globalCollapseResponseKey: data.globalCollapseResponseKey,\r\n globalCollapseTriggerKey: null,\r\n }\r\n : {\r\n isGroupedRow: false,\r\n order: null,\r\n groupingLevel: null,\r\n groupingKey1: null,\r\n groupingKey2: null,\r\n globalCollapseResponseKey: data.globalCollapseResponseKey,\r\n globalCollapseTriggerKey: null,\r\n },\r\n });\r\n\r\n if (data.showTopBorders) {\r\n rows[0].cells[0].cellAdditionalStyles!.push(\r\n 'border-top',\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n );\r\n }\r\n\r\n bidClassificationTypes.current.forEach((currClassificationType) => {\r\n const newRowObj: BTGridRowPrimary = {\r\n id: `${data.gridSectionId} - Bid Classification - ${currClassificationType.name}`,\r\n isPrimaryGridRow: true,\r\n cells: [],\r\n groupingLevel: null,\r\n isCollapsibleTrigger: false,\r\n collapseDirection: null,\r\n isHoverable: true,\r\n isSelectable: false,\r\n showBottomBorder: false,\r\n groupingInfo: {\r\n isGroupedRow: false,\r\n order: null,\r\n groupingLevel: null,\r\n groupingKey1: 'Adjustment Rows',\r\n groupingKey2: 'Classification',\r\n globalCollapseResponseKey: data.globalCollapseResponseKey,\r\n globalCollapseTriggerKey: null,\r\n },\r\n };\r\n\r\n newRowObj.cells.push({\r\n cellWidth: 'fill',\r\n cellContent:
    {currClassificationType.name}
    ,\r\n cellBackgroundColor: getCellbackgroundColorForBidClassificationType(\r\n currClassificationType.id,\r\n ),\r\n cellAdditionalStyles: ['border-sides'],\r\n });\r\n\r\n rows.push(newRowObj);\r\n });\r\n }\r\n\r\n const totalsRow: BTGridRowPrimary = {\r\n id: `${data.gridSectionId} - Adjustments Total Row`,\r\n isPrimaryGridRow: true,\r\n cells: [],\r\n groupingLevel: null,\r\n isCollapsibleTrigger: false,\r\n collapseDirection: null,\r\n isHoverable: true,\r\n isSelectable: false,\r\n showBottomBorder: false,\r\n };\r\n\r\n totalsRow.isCollapsibleTrigger = !data.bidPackage.isGeneralCondition;\r\n totalsRow.isCollapsedByDefault = !data.bidPackage.isGeneralCondition;\r\n\r\n totalsRow.groupingInfo = {\r\n isGroupedRow: false,\r\n order: null,\r\n groupingLevel: null,\r\n groupingKey1: 'Adjustment Rows',\r\n groupingKey2: null,\r\n globalCollapseResponseKey: data.globalCollapseResponseKey,\r\n globalCollapseTriggerKey: null,\r\n };\r\n\r\n totalsRow.collapseDirection = 'up';\r\n totalsRow.collapsibleIconJSXElementFactory = collapsibleIconJSXElementFactory;\r\n totalsRow.groupingLevel = 0;\r\n\r\n totalsRow.cells.push({\r\n cellWidth: 'fill',\r\n cellContent:

    {data.totalsTitle}

    ,\r\n cellBackgroundColor: 'dark-blue',\r\n cellAdditionalStyles: ['border-left', 'border-bottom', 'border-rounded-bottom-left'],\r\n });\r\n\r\n if (data.showTopBorders && data.collapseShouldIncludeAdjustmentsHeaderRow) {\r\n totalsRow.cells[0].cellAdditionalCollapseStyles = ['border-top', 'border-rounded-top-left'];\r\n }\r\n\r\n // Calculate the total\r\n let lineItems: BidPackageLineItem[] = [];\r\n\r\n if (data.isBidPackageTotalsSection) {\r\n const enabledAlternateIds = data.projectAlternates\r\n .filter((a) => a.enabled)\r\n .map((a) => a.id);\r\n\r\n lineItems = data.bidPackage.lineItems.filter(\r\n (v) => !v.alternateId || enabledAlternateIds.includes(v.alternateId),\r\n );\r\n } else {\r\n lineItems = data.bidPackage.getLineItems(data.alternate?.id || null);\r\n }\r\n\r\n let totalsValue: Big;\r\n\r\n // NOTE: For alternates that are not enabled, we show a total of 0\r\n if (data.alternate && !data.alternate.enabled) {\r\n totalsValue = new Big(0);\r\n } else {\r\n totalsValue = lineItems\r\n .map((li) => li.getBaseEstimate())\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n }\r\n\r\n totalsRow.cells.push({\r\n cellTriggersBTPopover: true,\r\n onCellMouseEnter: (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(totalsValue),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n },\r\n onCellMouseLeave: () => {\r\n setDisplayedPopoverInfo(null);\r\n },\r\n cellWidth: 'md',\r\n cellContent:
    {formatNumberAsCurrency(totalsValue)}
    ,\r\n cellBackgroundColor: 'dark-blue',\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-right', 'border-bottom', 'border-rounded-bottom-right'],\r\n });\r\n\r\n if (data.showTopBorders && data.collapseShouldIncludeAdjustmentsHeaderRow) {\r\n totalsRow.cells[1].cellAdditionalCollapseStyles = [\r\n 'border-top',\r\n 'border-rounded-top-right',\r\n ];\r\n }\r\n\r\n rows.push(totalsRow);\r\n\r\n // If this is a general conditions bid package and the totals section, there will only be one row so round off the corners\r\n if (data.bidPackage.isGeneralCondition && data.isBidPackageTotalsSection) {\r\n rows[0].cells[0].cellAdditionalStyles?.push('border-top', 'border-rounded-top-left');\r\n rows[0].cells[1].cellAdditionalStyles?.push('border-top', 'border-rounded-top-right');\r\n }\r\n\r\n return {\r\n id: `${data.gridSectionId} - ${data.gridSectionTestId}`,\r\n testId: `${data.gridSectionTestId}_PrimarySubGrid`,\r\n auxiliaryRows: [],\r\n rows: rows,\r\n addLeftPadding: false,\r\n };\r\n },\r\n [bidClassificationTypes, setDisplayedPopoverInfo, t],\r\n );\r\n\r\n const generateSubGrids_Bidders = useCallback(\r\n (data: {\r\n isBidPackageTotalsSection: boolean;\r\n isReadOnly: boolean;\r\n gridSectionId: string;\r\n gridSectionTestId: string;\r\n alternate: Alternate | null;\r\n bidPackage: BidPackage;\r\n projectAlternates: Alternate[];\r\n allowEntryInAdjustmentsRow: boolean;\r\n showTopBorders: boolean;\r\n collapseShouldIncludeAdjustmentsHeaderRow: boolean;\r\n }): BTSubGrid[] => {\r\n const returnValue: BTSubGrid[] = [];\r\n\r\n data.bidPackage.bidders.forEach((currBidder) => {\r\n const bidderRows: BTGridRowBase[] = [];\r\n\r\n // Add a row for the adjustment\r\n const adjustmentRow: BTGridRowBase = {\r\n id: `${data.gridSectionId} - 99a3e01d-78b4-491a-b07a-a9b599b5d0d2`,\r\n cells: [\r\n {\r\n cellContent:
    {data.isBidPackageTotalsSection ? ' ' :

     

    }
    ,\r\n cellWidth: 'md',\r\n cellBackgroundColor: 'green',\r\n cellAdditionalStyles: ['border-sides'],\r\n cellHorizontalAlignment: 'right',\r\n },\r\n ],\r\n isPrimaryGridRow: false,\r\n showBottomBorder: false,\r\n };\r\n\r\n // The adjustment section will be displayed for all sections. Now the question is, will the value be editable or not?!?\r\n let adjustmentBidValue: number | null = 0;\r\n if (data.isBidPackageTotalsSection) {\r\n // lets get all of the ids of alternates that are enabled\r\n const enabledAlternateIds = data.projectAlternates\r\n .filter((a) => a.enabled)\r\n .map((a) => a.id);\r\n\r\n adjustmentBidValue = data.bidPackage.adjustments\r\n .filter(\r\n (v) =>\r\n v.bidderId === currBidder.id &&\r\n (!v.alternateId || enabledAlternateIds.includes(v.alternateId)),\r\n )\r\n .map((v) => v.value || 0)\r\n .reduce((sum, curr) => sum.add(curr), new Big(0))\r\n .toNumber();\r\n } else {\r\n // NOTE: We want to allow this to be 0 so we don't give it a falsey fallback value\r\n adjustmentBidValue =\r\n data.bidPackage.adjustments.find(\r\n (v) =>\r\n v.bidderId === currBidder.id &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(data.alternate?.id),\r\n )?.value ?? null;\r\n }\r\n\r\n const adjustmentNotes =\r\n data.bidPackage.adjustments.find(\r\n (a) =>\r\n normalizeNullOrUndefined(a.alternateId) ===\r\n normalizeNullOrUndefined(data.alternate?.id) &&\r\n normalizeNullOrUndefined(a.bidderId) ===\r\n normalizeNullOrUndefined(currBidder?.id),\r\n )?.notes || '';\r\n\r\n // are we going to allow them to edit the adjustment or not?!?\r\n if (data.allowEntryInAdjustmentsRow) {\r\n adjustmentRow.cells[0].cellTriggersBTPopover = adjustmentBidValue ? true : false;\r\n adjustmentRow.cells[0].onCellMouseEnter = (e) => {\r\n if (adjustmentBidValue) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(adjustmentBidValue || 0),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n };\r\n\r\n adjustmentRow.cells[0].onCellMouseLeave = () => {\r\n if (adjustmentBidValue) {\r\n setDisplayedPopoverInfo(null);\r\n }\r\n };\r\n\r\n const customDataAttributes: Record = {};\r\n\r\n if (adjustmentNotes.length > 0) {\r\n customDataAttributes['data-triggers-popover'] = '';\r\n }\r\n\r\n adjustmentRow.cells[0].cellContent = (\r\n {\r\n adjustment_OpenNote({\r\n alternateId: data.alternate?.id ?? null,\r\n bidderId: currBidder.id || '',\r\n });\r\n },\r\n },\r\n ]}\r\n >\r\n
    \r\n {getInputElementForBidField({\r\n inputType: 'number',\r\n isLineItem: false,\r\n price: adjustmentBidValue as number,\r\n value: undefined,\r\n classification: undefined,\r\n placeholder: undefined,\r\n isDisabled: data.isReadOnly,\r\n onBidChangeCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n if (data.allowEntryInAdjustmentsRow) {\r\n adjustment_Change({\r\n bidderId: currBidder.id || '',\r\n alternateId: data.alternate?.id || undefined,\r\n value: bidderValue.price ?? undefined,\r\n });\r\n }\r\n },\r\n onBidBlurCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n if (data.allowEntryInAdjustmentsRow) {\r\n adjustment_Blur({\r\n bidderId: currBidder.id || '',\r\n alternateId: data.alternate?.id || undefined,\r\n value: bidderValue.price ?? undefined,\r\n });\r\n }\r\n },\r\n allowedNonNumericKeys: [GeneralConstants.KEY_N],\r\n onKeyDownCallback: (e: KeyboardEvent) => {\r\n // If the user pressed \"Alt + N\", open the adjustment notes\r\n if (e.altKey && e.key.toUpperCase() === GeneralConstants.KEY_N) {\r\n adjustment_OpenNote({\r\n alternateId: data.alternate?.id ?? null,\r\n bidderId: currBidder.id || '',\r\n });\r\n }\r\n },\r\n })}\r\n\r\n 0 ? 'd-block' : 'gray'\r\n } ${data.isReadOnly ? 'isReadOnly' : ''}`}\r\n title={\r\n adjustmentNotes.length > 0 ? '' : `${t('general:add')} ${t('general:notes')}`\r\n }\r\n {...customDataAttributes}\r\n onMouseEnter={(e) => {\r\n if (adjustmentNotes.length) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: adjustmentNotes || t('general:noNotes'),\r\n title: t('bid-package:adjustmentNotes'),\r\n placement: 'bottom',\r\n showCloseButton: true,\r\n });\r\n }\r\n }}\r\n onClick={() => {\r\n adjustment_OpenNote({\r\n alternateId: data.alternate?.id ?? null,\r\n bidderId: currBidder.id || '',\r\n });\r\n }}\r\n >\r\n \r\n
    \r\n \r\n \r\n );\r\n } else {\r\n adjustmentRow.cells[0].cellTriggersBTPopover = true;\r\n adjustmentRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(adjustmentBidValue || 0),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n adjustmentRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n adjustmentRow.cells[0].cellContent = (\r\n
    \r\n {adjustmentBidValue === null ? '' : formatNumberAsCurrency(adjustmentBidValue)}\r\n
    \r\n );\r\n }\r\n\r\n if (data.showTopBorders) {\r\n adjustmentRow.cells[0].cellAdditionalStyles!.push(\r\n 'border-top',\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n );\r\n }\r\n\r\n bidderRows.push(adjustmentRow);\r\n\r\n const allLineItemsWithBidForCurrBidder: BidPackageLineItem[] = [];\r\n\r\n // TODO - this code needs to be refactored or moved into a new method\r\n if (data.isBidPackageTotalsSection) {\r\n // lets get all of the ids of alternates that are enabled\r\n const enabledAlternateIds = data.projectAlternates\r\n .filter((a) => a.enabled)\r\n .map((a) => a.id);\r\n\r\n // lets get the line items that either do not belong to an alternate or belong to an alternate that is enabled\r\n allLineItemsWithBidForCurrBidder.push(\r\n ...data.bidPackage.lineItems.filter(\r\n (v) =>\r\n !v.alternateId ||\r\n (enabledAlternateIds.includes(v.alternateId) &&\r\n v.bids.some((m) => m.bidderId === currBidder.id)),\r\n ),\r\n );\r\n } else {\r\n allLineItemsWithBidForCurrBidder.push(\r\n ...data.bidPackage\r\n .getLineItems(data.alternate?.id || null)\r\n .filter((v) => v.bids.some((m) => m.bidderId === currBidder.id)),\r\n );\r\n }\r\n\r\n // Generate rows for the classification types\r\n bidClassificationTypes.current.forEach((currClassificationType) => {\r\n let lineItemBidsTotal = allLineItemsWithBidForCurrBidder\r\n .filter((v) => {\r\n const matchingBid = v.bids.find((m) => m.bidderId === currBidder.id);\r\n return matchingBid && matchingBid.classification === currClassificationType.id;\r\n })\r\n .map((v) => data.bidPackage.calculateLineItemBidValue(v, currBidder.id!))\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n // If the current classification type is \"sub bid\", we want to include values from the line item breakdown bids\r\n if (currClassificationType.id === BidClassificationTypes.SubBid) {\r\n let lineItemRollupBidsValue = new Big(0);\r\n\r\n if (data.isBidPackageTotalsSection) {\r\n // lets get all of the ids of alternates that are enabled\r\n const enabledAlternateIds = data.projectAlternates\r\n .filter((a) => a.enabled)\r\n .map((a) => a.id);\r\n\r\n lineItemRollupBidsValue = data.bidPackage.lineItemRollupBids\r\n .filter(\r\n (v) =>\r\n v.bidderId === currBidder.id &&\r\n (!v.alternateId || enabledAlternateIds.includes(v.alternateId)),\r\n )\r\n .map((v) => v.bidValue || 0)\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n } else {\r\n // sum up all of the rollup bids for this bidder based on the whether we're looking at a specific alternate or just the base line items bid\r\n lineItemRollupBidsValue = data.bidPackage.lineItemRollupBids\r\n .filter(\r\n (v) =>\r\n v.bidderId === currBidder.id &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(data.alternate?.id),\r\n )\r\n .map((v) => v.bidValue || 0)\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n }\r\n\r\n lineItemBidsTotal = lineItemBidsTotal.add(lineItemRollupBidsValue);\r\n }\r\n\r\n let requirementFulfillmentValues = new Big(0);\r\n\r\n if (!data.alternate?.id) {\r\n requirementFulfillmentValues = data.bidPackage.requirements\r\n .filter(\r\n (v) => v.requirementFulfillmentType === RequirementFulfillmentTypes.Quantitative,\r\n )\r\n .map((v) => {\r\n if (\r\n v.requirementFulfillments.some(\r\n (rf) =>\r\n rf.classification === currClassificationType.id &&\r\n rf.bidderId === currBidder.id,\r\n )\r\n ) {\r\n return BidPackage.calculateRequirementFulfillmentBidValue(v, currBidder.id!);\r\n }\r\n\r\n return new Big(0);\r\n })\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n }\r\n\r\n const totalClassificationPrice = lineItemBidsTotal.add(requirementFulfillmentValues);\r\n\r\n bidderRows.push({\r\n id: `${data.gridSectionId} - Bidder Adjustment Bid Classification - ${currBidder.id} - ${currClassificationType.name}`,\r\n cells: [\r\n {\r\n testId: `${currClassificationType.name.replace(/ /g, '_')}`,\r\n cellTriggersBTPopover: true,\r\n onCellMouseEnter: (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(totalClassificationPrice),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n },\r\n onCellMouseLeave: () => {\r\n setDisplayedPopoverInfo(null);\r\n },\r\n cellContent:
    {formatNumberAsCurrency(totalClassificationPrice)}
    ,\r\n cellWidth: 'md',\r\n cellBackgroundColor: getCellbackgroundColorForBidClassificationType(\r\n currClassificationType.id,\r\n ),\r\n cellAdditionalStyles: ['border-sides'],\r\n cellHorizontalAlignment: 'right',\r\n },\r\n ],\r\n isPrimaryGridRow: false,\r\n showBottomBorder: false,\r\n });\r\n });\r\n\r\n // For disabled alternates, we show a total of 0, since these aren't factored into the grand total\r\n const totalValue =\r\n !data.alternate || data.alternate.enabled\r\n ? getTotalValueForBidder(\r\n data.bidPackage,\r\n data.isBidPackageTotalsSection,\r\n currBidder.id!,\r\n data.alternate?.id || null,\r\n data.projectAlternates,\r\n )\r\n : 0;\r\n\r\n // Add a row for the total\r\n const totalsRow: BTGridRowBase = {\r\n id: `${data.gridSectionId} - 4ea40e90-34ce-4766-b611-15316a592ac4`,\r\n cells: [\r\n {\r\n testId: `Total`,\r\n cellTriggersBTPopover: true,\r\n onCellMouseEnter: (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(totalValue),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n },\r\n onCellMouseLeave: () => {\r\n setDisplayedPopoverInfo(null);\r\n },\r\n cellContent:
    {formatNumberAsCurrency(totalValue)}
    ,\r\n cellWidth: 'md',\r\n cellBackgroundColor: 'dark-blue',\r\n cellAdditionalStyles: [\r\n 'border-sides',\r\n 'border-bottom',\r\n 'border-rounded-bottom-left',\r\n 'border-rounded-bottom-right',\r\n ],\r\n cellHorizontalAlignment: 'right',\r\n },\r\n ],\r\n isPrimaryGridRow: false,\r\n showBottomBorder: false,\r\n };\r\n\r\n if (data.showTopBorders && data.collapseShouldIncludeAdjustmentsHeaderRow) {\r\n totalsRow.cells[0].cellAdditionalCollapseStyles = [\r\n 'border-top',\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n ];\r\n }\r\n\r\n bidderRows.push(totalsRow);\r\n\r\n const testId = `${data.gridSectionTestId}_SubGrid_${currBidder!.companyName!.replace(\r\n / /g,\r\n '_',\r\n )}`;\r\n\r\n returnValue.push({\r\n id: `Bidder SubGrid - Adjustment - ${data.gridSectionId} - ${testId}`,\r\n testId: testId,\r\n auxiliaryRows: [],\r\n rows: bidderRows,\r\n addLeftPadding: true,\r\n });\r\n });\r\n\r\n return returnValue;\r\n },\r\n [\r\n adjustment_Blur,\r\n adjustment_Change,\r\n adjustment_OpenNote,\r\n bidClassificationTypes,\r\n getInputElementForBidField,\r\n setDisplayedPopoverInfo,\r\n t,\r\n ],\r\n );\r\n\r\n const getTotalValueForBidder = (\r\n bidPackage: BidPackage,\r\n isBidPackageTotalsSection: boolean,\r\n bidderId: string,\r\n alternateId: string | null,\r\n projectAlternates: Alternate[],\r\n ): number => {\r\n if (isBidPackageTotalsSection) {\r\n // NOTE: The total here is made up of the following:\r\n // - High level bids\r\n // - Line item bids\r\n // - Line item breakdown bids\r\n // - Requirements with fulfillments of type 'Quantitative'\r\n // - Adjustment value\r\n\r\n // lets get all of the ids of alternates that are enabled\r\n const enabledAlternateIds = projectAlternates.filter((a) => a.enabled).map((a) => a.id);\r\n\r\n // lets get the line items that either do not belong to an alternate or belong to an alternate that is enabled\r\n const lineItemBidValue = bidPackage.lineItems\r\n .filter((v) => !v.alternateId || enabledAlternateIds.includes(v.alternateId))\r\n .map((v) => bidPackage.calculateLineItemBidValue(v, bidderId))\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n // lets get the line item rollup bids that either do not belong to an alternate or belong to an alternate that is enabled\r\n const lineItemRollupBidsValue = bidPackage.lineItemRollupBids\r\n .filter(\r\n (v) =>\r\n v.bidderId === bidderId &&\r\n (!v.alternateId || enabledAlternateIds.includes(v.alternateId)),\r\n )\r\n .map((v) => v.bidValue || 0)\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n const requirementsFulfillmentsValue = bidPackage.requirements\r\n .filter((r) => r.requirementFulfillmentType === RequirementFulfillmentTypes.Quantitative)\r\n .map((r) => {\r\n return BidPackage.calculateRequirementFulfillmentBidValue(r, bidderId)!;\r\n })\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n // lets get the adjustments that either do not belong to an alternate or belong to an alternate that is enabled\r\n const adjustmentsValue = bidPackage.adjustments\r\n .filter(\r\n (v) =>\r\n v.bidderId === bidderId &&\r\n (!v.alternateId || enabledAlternateIds.includes(v.alternateId)),\r\n )\r\n .map((v) => v.value || 0)\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n return [\r\n lineItemBidValue,\r\n lineItemRollupBidsValue,\r\n requirementsFulfillmentsValue,\r\n adjustmentsValue,\r\n ]\r\n .reduce((sum, curr) => sum.add(curr), new Big(0))\r\n .toNumber();\r\n } else {\r\n let lineItemBidValue = new Big(0);\r\n let lineItemRollupBidsValue = new Big(0);\r\n let requirementfulfillmentsValue = new Big(0);\r\n let adjustmentValue = new Big(0);\r\n\r\n lineItemBidValue = bidPackage.lineItems\r\n .filter(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId),\r\n )\r\n .map((v) => bidPackage.calculateLineItemBidValue(v, bidderId))\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n // sum up all of the rollup bids for this bidder\r\n lineItemRollupBidsValue = bidPackage.lineItemRollupBids\r\n .filter(\r\n (v) =>\r\n v.bidderId === bidderId &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId),\r\n )\r\n .map((v) => v.bidValue || 0)\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n // If there is no alternate, we want to include the totals for quantitative requirement fulfillments\r\n if (!alternateId) {\r\n requirementfulfillmentsValue = bidPackage.requirements\r\n .filter((v) => v.requirementFulfillmentType === RequirementFulfillmentTypes.Quantitative)\r\n .map((r) => {\r\n return BidPackage.calculateRequirementFulfillmentBidValue(r, bidderId)!;\r\n })\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n }\r\n\r\n // sum up the adjustments for this bidder\r\n adjustmentValue = new Big(\r\n bidPackage.adjustments.find(\r\n (v) =>\r\n v.bidderId === bidderId &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternateId),\r\n )?.value || 0,\r\n );\r\n\r\n return [\r\n lineItemBidValue,\r\n lineItemRollupBidsValue,\r\n requirementfulfillmentsValue,\r\n adjustmentValue,\r\n ]\r\n .reduce((sum, curr) => sum.add(curr), new Big(0))\r\n .toNumber();\r\n }\r\n };\r\n\r\n const generateBidPackage_Adjustments_GridSection = useCallback(\r\n (data: GenerateBidPackage_Adjustments_GridSection_Params): BTGridSection | null => {\r\n if (!data.bidPackage) {\r\n return null;\r\n }\r\n\r\n // NOTE: The alternate name should be included in the totals title text\r\n const gridSectionTestId =\r\n 'BidPackagePage_GridSection_Adjustments_' + data.totalsTitle.replace(/ /g, '_');\r\n\r\n const adjustmentSubGrid = generateSubGrid_AdjustmentsAndBidClassifications({\r\n bidPackage: data.bidPackage,\r\n projectAlternates: data.projectAlternates,\r\n isBidPackageTotalsSection: data.isBidPackageTotalsSection,\r\n gridSectionId: data.gridSectionId,\r\n gridSectionTestId,\r\n alternate: data.alternate,\r\n totalsTitle: data.totalsTitle,\r\n showTopBorders: data.showTopBorders,\r\n collapseShouldIncludeAdjustmentsHeaderRow: data.collapseShouldIncludeAdjustmentsHeaderRow,\r\n globalCollapseResponseKey: data.globalCollapseResponseKey,\r\n });\r\n\r\n const bidderSubGrids = generateSubGrids_Bidders({\r\n isBidPackageTotalsSection: data.isBidPackageTotalsSection,\r\n isReadOnly: data.isReadOnly,\r\n gridSectionId: data.gridSectionId,\r\n gridSectionTestId,\r\n alternate: data.alternate,\r\n bidPackage: data.bidPackage,\r\n projectAlternates: data.projectAlternates,\r\n allowEntryInAdjustmentsRow: data.allowEntryInAdjustmentsRow,\r\n showTopBorders: data.showTopBorders,\r\n collapseShouldIncludeAdjustmentsHeaderRow: data.collapseShouldIncludeAdjustmentsHeaderRow,\r\n });\r\n\r\n return {\r\n id: data.gridSectionId,\r\n primaryGrid: adjustmentSubGrid,\r\n secondaryGrids: bidderSubGrids,\r\n testId: gridSectionTestId,\r\n };\r\n },\r\n [generateSubGrid_AdjustmentsAndBidClassifications, generateSubGrids_Bidders],\r\n );\r\n\r\n return { generateBidPackage_Adjustments_GridSection };\r\n};\r\n\r\nexport default useBidPackageGrid_Adjustments;\r\n","import React, { useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Bidder } from '../../../../../classes/odata/bidder';\r\nimport BidPackageConstants from '../../../../../constants/bid-package';\r\nimport BTIconButtonToggle from '../../../../common-page-components/controls/icon-button-toggle/BTIconButtonToggle';\r\nimport useBidPackagePageContext from '../BidPackagePageContext';\r\n\r\ninterface ReturnValue {\r\n generateBidPackage_Header_GridSection: (\r\n isGeneralCondition: boolean,\r\n isReadOnly: boolean,\r\n bidders: Bidder[] | undefined,\r\n ) => BTGridSection | null;\r\n}\r\n\r\nconst useBidPackageGrid_Header = (): ReturnValue => {\r\n const { bidders_Add } = useBidPackagePageContext();\r\n\r\n const { t } = useTranslation();\r\n\r\n const generateSubGrid_LineItemsHeader = useCallback(\r\n (isGeneralCondition: boolean, gridSectionTestId: string): BTSubGrid => {\r\n const auxiliaryRows: BTGridRowBase[] = [];\r\n\r\n if (!isGeneralCondition) {\r\n auxiliaryRows.push({\r\n id: 'cd4a52a7-1022-4423-9e41-960710057d33',\r\n isPrimaryGridRow: true,\r\n showBottomBorder: false,\r\n cells: [\r\n {\r\n cellContent: (\r\n <>\r\n // TODO - these buttons will be wired up later\r\n\r\n //
    \r\n // {\r\n // // TODO\r\n // }}\r\n // value={false}\r\n // />\r\n\r\n // {bidPackage?.isGeneralCondition ?? false ? (\r\n // <>\r\n // ) : (\r\n // {\r\n // // TODO\r\n // }}\r\n // value={false}\r\n // />\r\n // )}\r\n //
    \r\n ),\r\n cellWidth: 'fill',\r\n },\r\n ],\r\n });\r\n }\r\n\r\n const testId = `${gridSectionTestId}_PrimarySubGrid`;\r\n\r\n return {\r\n id: 'd7d66bb0-8f0c-4558-80cf-9efc7dce4999',\r\n testId: testId,\r\n auxiliaryRows: auxiliaryRows,\r\n rows: [],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [],\r\n );\r\n\r\n const generateSubGrids_Bidders = useCallback(\r\n (\r\n isGeneralCondition: boolean,\r\n isReadOnly: boolean,\r\n gridSectionTestId: string,\r\n bidders: Bidder[],\r\n ): BTSubGrid[] => {\r\n const returnValue: BTSubGrid[] = [];\r\n\r\n const auxiliaryRows: BTGridRowBase[] = [];\r\n\r\n if (!isGeneralCondition) {\r\n auxiliaryRows.push({\r\n id: 'e6d253bf-ccd7-4da5-82a6-a958fd7a384e',\r\n cells: [\r\n {\r\n cellContent: (\r\n
    \r\n {isReadOnly && bidders.length === 0 ? (\r\n <>\r\n ) : (\r\n \r\n )}\r\n\r\n
    \r\n {!isReadOnly && bidders.length < 20 ? (\r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {bidders.length > 0 ? (\r\n
    \r\n \r\n {bidders.length}\r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n \r\n ),\r\n cellWidth: 'md',\r\n },\r\n ],\r\n isPrimaryGridRow: false,\r\n showBottomBorder: false,\r\n });\r\n }\r\n\r\n const testId = `${gridSectionTestId}_SubGrid`;\r\n\r\n returnValue.push({\r\n id: '94edb728-db0e-40c3-9d8d-15ba9ec13767',\r\n testId: testId,\r\n auxiliaryRows: auxiliaryRows,\r\n rows: [],\r\n addLeftPadding: true,\r\n });\r\n\r\n return returnValue;\r\n },\r\n [bidders_Add, t],\r\n );\r\n\r\n const generateBidPackage_Header_GridSection = useCallback(\r\n (\r\n isGeneralCondition: boolean,\r\n isReadOnly: boolean,\r\n bidders: Bidder[] | undefined,\r\n ): BTGridSection | null => {\r\n bidders = bidders || [];\r\n\r\n const gridSectionTestId = 'BidPackagePage_GridSection_Header';\r\n\r\n const lineItemsSubGrid = generateSubGrid_LineItemsHeader(\r\n isGeneralCondition,\r\n gridSectionTestId,\r\n );\r\n\r\n let biddersSubGrids: BTSubGrid[] = [];\r\n\r\n if (!isGeneralCondition) {\r\n biddersSubGrids = generateSubGrids_Bidders(\r\n isGeneralCondition,\r\n isReadOnly,\r\n gridSectionTestId,\r\n bidders,\r\n );\r\n }\r\n\r\n return {\r\n id: BidPackageConstants.GridSectionIds.BID_PACKAGE_HEADER,\r\n primaryGrid: lineItemsSubGrid!,\r\n secondaryGrids: biddersSubGrids,\r\n testId: gridSectionTestId,\r\n };\r\n },\r\n [generateSubGrid_LineItemsHeader, generateSubGrids_Bidders],\r\n );\r\n\r\n return { generateBidPackage_Header_GridSection };\r\n};\r\n\r\nexport default useBidPackageGrid_Header;\r\n","import { NumericTextBoxBlurEvent, NumericTextBoxChangeEvent } from '@progress/kendo-react-inputs';\r\nimport { clone } from 'lodash';\r\nimport React, { useCallback } from 'react';\r\nimport BTNumericInput, {\r\n BTNumericInputFormat,\r\n} from '../../../common-page-components/inputs/BTNumericInput';\r\n\r\ntype InputType = 'number' | 'text';\r\n\r\ninterface HelperHookReturnValue {\r\n getUpdatableInputElement: (\r\n sourceObject: unknown,\r\n propertyName: string,\r\n inputType: InputType,\r\n isShortInput: boolean,\r\n onChangeCallback: (updatedObject: unknown) => void,\r\n onBlurCallback: (field: string, updatedObject: unknown) => void,\r\n onKeyDownCallback?: (e: KeyboardEvent) => void,\r\n inputFormat?: BTNumericInputFormat,\r\n ) => JSX.Element;\r\n}\r\n\r\nconst useHelperHook = (): HelperHookReturnValue => {\r\n const getNewInputValue = useCallback(\r\n (newValue: string | number, originalValue: number): number => {\r\n newValue = (newValue || '').toString().trim();\r\n\r\n if (!newValue) {\r\n return 0;\r\n } else {\r\n return !isNaN(parseFloat(newValue)) ? parseFloat(newValue) : originalValue;\r\n }\r\n },\r\n [],\r\n );\r\n\r\n const getUpdatableInputElement = useCallback(\r\n (\r\n sourceObject: unknown,\r\n propertyName: string,\r\n inputType: InputType,\r\n isShortInput: boolean,\r\n onChangeCallback: (updatedObject: unknown) => void,\r\n onBlurCallback: (field: string, value: unknown) => void,\r\n onKeyDownCallback?: (e: KeyboardEvent) => void,\r\n inputFormat?: BTNumericInputFormat,\r\n ): JSX.Element => {\r\n const onChangeCallbackFn = (\r\n inputElement: React.ChangeEvent | NumericTextBoxChangeEvent,\r\n ) => {\r\n // TODO - for now, this is numeric only\r\n const newValue = getNewInputValue(\r\n inputElement.target.value as string,\r\n ((sourceObject as Dictionary)[propertyName] as unknown) as number,\r\n );\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const updatedObject = clone(sourceObject) as { [key: string]: any };\r\n updatedObject[propertyName] = newValue;\r\n\r\n onChangeCallback(updatedObject);\r\n };\r\n\r\n const onBlurCallbackFn = (\r\n e: React.FocusEvent | NumericTextBoxBlurEvent,\r\n ) => {\r\n onBlurCallback(propertyName, sourceObject);\r\n };\r\n\r\n const onKeyDownCallbackFn = (e: KeyboardEvent) => {\r\n if (onKeyDownCallback) {\r\n onKeyDownCallback(e);\r\n }\r\n };\r\n\r\n if (inputType === 'number') {\r\n // NOTE: For now, the \"short input\" logic doesn't apply to numeric inputs\r\n return (\r\n )[propertyName]}\r\n onChange={onChangeCallbackFn}\r\n onBlur={onBlurCallbackFn}\r\n onKeyDown={onKeyDownCallbackFn}\r\n allowAnyKeysToPassThrough\r\n format={inputFormat}\r\n />\r\n );\r\n }\r\n\r\n return (\r\n )[propertyName]}\r\n onChange={onChangeCallbackFn}\r\n onBlur={onBlurCallbackFn}\r\n onFocus={(event) => event.target.select()}\r\n onKeyDown={(e) => {\r\n onKeyDownCallbackFn((e as unknown) as KeyboardEvent);\r\n }}\r\n />\r\n );\r\n },\r\n [getNewInputValue],\r\n );\r\n\r\n return { getUpdatableInputElement };\r\n};\r\n\r\nexport default useHelperHook;\r\n","import Big from 'big.js';\nimport { clone, groupBy, sortBy } from 'lodash';\nimport React, { useCallback, useContext, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Subscription } from 'rxjs';\nimport { BidPackageLineItem } from '../../../../../../classes/odata/bid-package-line-item';\nimport GeneralConstants from '../../../../../../constants/general';\nimport { generateGridRow_Grouped } from '../../../../../../utils/btgrid';\nimport {\n formatNumberAsCurrency,\n formatNumberAsCurrencyFull,\n formatNumberAsDecimal,\n} from '../../../../../../utils/general';\nimport { nameof } from '../../../../../../utils/nameof';\nimport { BTDropdownMenuItem } from '../../../../../common-page-components/context-menu/BTContextMenu';\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\nimport useHelperHook from '../../../helper-hooks/useHelperHook';\nimport { LineItemGridRowSortableContainerId } from '../../BidPackagePage';\nimport useBidPackagePageContext from '../../BidPackagePageContext';\n\ninterface ReturnValue {\n getGroupedLineItemRows: (\n isReadOnly: boolean,\n lineItems: LineItemValue[],\n lineItemGroupOrders: LineItemGroupOrderValue[],\n lineItemRollup1: string,\n lineItemRollup2: string,\n unitsOfMeasureDropdownListOptions: string[],\n onChangeCallback: (updatedObject: unknown) => void,\n onBlurCallback: (updatedLineItem: LineItemValue) => void,\n lineItemEditCallback: (lineItemId: string) => void,\n lineItemsEditCallback: () => void,\n lineItemDeleteCallback: (lineItemId: string) => void,\n lineItemsDeleteCallback: () => void,\n globalCollapseResponseKey: string | null,\n alternateId: string | null,\n alternateName: string | null,\n ) => BTGridRowPrimary[];\n}\n\nconst useLineItemsHelpers = (): ReturnValue => {\n const { t } = useTranslation();\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\n const { getUpdatableInputElement } = useHelperHook();\n\n const generateGridRowForLineItem_Details = useCallback(\n (data: {\n isReadOnly: boolean;\n lineItem: LineItemValue;\n unitsOfMeasureDropdownListOptions: string[];\n isSelectable: boolean;\n groupingLevel: number;\n onChangeCallback: (updatedObject: LineItemValue) => void;\n onBlurCallback: (updatedLineItem: LineItemValue) => void;\n lineItemEditCallback: (lineItemId: string) => void;\n lineItemsEditCallback: () => void;\n lineItemDeleteCallback: (lineItemId: string) => void;\n lineItemsDeleteCallback: () => void;\n groupingKey1: string | null;\n groupingKey2: string | null;\n groupingParent1Info?: BTGridRowGroupingParentInfo;\n groupingParent2Info?: BTGridRowGroupingParentInfo;\n globalCollapseResponseKey: string | null;\n alternateId: string | null;\n alternateName: string | null;\n }): BTGridRowPrimary => {\n const contextMenuOptions: BTContextMenuItem[] = [];\n\n if (!data.isReadOnly) {\n contextMenuOptions.push({\n id: 'Edit',\n icon: 'edit',\n text: t('general:edit'),\n onClick: () => {\n data.lineItemEditCallback(data.lineItem.id!);\n },\n });\n\n contextMenuOptions.push({\n id: 'Delete',\n icon: 'trash',\n text: t('general:delete'),\n onClick: () => {\n data.lineItemDeleteCallback(data.lineItem.id!);\n },\n });\n }\n\n const setPopoverForQuantityCell = (e: MouseEvent) => {\n setDisplayedPopoverInfo({\n element: e.target as HTMLElement,\n text: '',\n title: formatNumberAsDecimal(\n new Big(data.lineItem.quantity || 0),\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MAXIMUM_FRACTION_DIGITS,\n ),\n placement: 'top',\n showCloseButton: false,\n });\n };\n\n const setPopoverForUnitPriceCell = (e: MouseEvent) => {\n setDisplayedPopoverInfo({\n element: e.target as HTMLElement,\n text: '',\n title: formatNumberAsCurrencyFull(data.lineItem.unitPrice || 0),\n placement: 'top',\n showCloseButton: false,\n });\n };\n\n const removePopover = () => {\n setDisplayedPopoverInfo(null);\n };\n\n const newRowObj: BTGridRowPrimary = {\n id: data.lineItem.id!,\n isPrimaryGridRow: true,\n cells: [],\n groupingLevel: data.groupingLevel,\n collapseDirection: null,\n isCollapsibleTrigger: false,\n isHoverable: true,\n isSelectable: data.isSelectable,\n groupingInfo: {\n isGroupedRow: false,\n order: data.lineItem.mappedOrder?.order,\n groupingLevel: data.groupingLevel,\n groupingKey1: data.groupingKey1,\n groupingKey2: data.groupingKey2,\n groupingParent1Info: data.groupingParent1Info,\n groupingParent2Info: data.groupingParent2Info,\n globalCollapseResponseKey: data.globalCollapseResponseKey,\n globalCollapseTriggerKey: null,\n },\n contextMenuItems: contextMenuOptions,\n contextMenuItemsJSX: (\n \n ),\n dataAttributes: {\n 'alternate-name': data.alternateName || '',\n 'line-item-description': data.lineItem.description || '',\n 'line-item-metadata1': data.groupingKey1 || '',\n 'line-item-metadata2': data.groupingKey2 || '',\n 'line-item-order': data.lineItem.mappedOrder?.order.toString() || '',\n },\n sortableInfo: !data.isReadOnly\n ? {\n sortableContainerId: data.alternateId\n ? `${LineItemGridRowSortableContainerId}-${data.alternateId}`\n : LineItemGridRowSortableContainerId,\n sortableDirection: 'vertical',\n }\n : undefined,\n };\n\n newRowObj.cells.push({\n cellWidth: 'xl',\n cellContent: (\n // NOTE: The nested divs are important here, for the cell content overflow CSS to work correctly\n
    \n
    {data.lineItem.description}
    \n
    \n ),\n dataAttributes: {\n 'column-name': 'description',\n },\n cellTriggersBTPopover: true,\n onCellMouseEnter: (e) => {\n setDisplayedPopoverInfo({\n element: e.target as HTMLElement,\n text: data.lineItem.description || '',\n title: '',\n placement: 'bottom',\n showCloseButton: false,\n });\n },\n onCellMouseLeave: () => {\n setDisplayedPopoverInfo(null);\n },\n frozenOnHorizontalScroll: true,\n trimTextOnOverflow: true,\n });\n\n // NOTE: The unit of measure on the line item is just a string so match it to the dropdown option\n let matchingDropdownOption = data.unitsOfMeasureDropdownListOptions.find(\n (v) =>\n (v || '').trim().toLowerCase() ===\n (data.lineItem.quantityUnitOfMeasure || '').trim().toLowerCase(),\n );\n\n if (!matchingDropdownOption) {\n matchingDropdownOption = data.unitsOfMeasureDropdownListOptions[0];\n }\n\n if (data.isReadOnly) {\n newRowObj.cells.push({\n cellTriggersBTPopover: true,\n onCellMouseEnter: setPopoverForQuantityCell,\n onCellMouseLeave: removePopover,\n cellWidth: 'sm',\n cellContent:
    {formatNumberAsDecimal(data.lineItem.quantity || 0)}
    ,\n cellHorizontalAlignment: 'right',\n dataAttributes: {\n 'column-name': 'quantity',\n },\n });\n\n newRowObj.cells.push({\n cellWidth: 'sm',\n cellContent:
    {matchingDropdownOption}
    ,\n cellHorizontalAlignment: 'left',\n dataAttributes: {\n 'column-name': 'unit-of-measure',\n },\n });\n\n newRowObj.cells.push({\n cellTriggersBTPopover: true,\n onCellMouseEnter: setPopoverForUnitPriceCell,\n onCellMouseLeave: removePopover,\n cellWidth: 'sm',\n cellContent:
    {formatNumberAsCurrency(data.lineItem.unitPrice || 0)}
    ,\n cellHorizontalAlignment: 'right',\n dataAttributes: {\n 'column-name': 'unit-price',\n },\n });\n } else {\n newRowObj.cells.push({\n cellTriggersBTPopover: true,\n onCellMouseEnter: setPopoverForQuantityCell,\n onCellMouseLeave: removePopover,\n cellWidth: 'sm',\n cellContent: getUpdatableInputElement(\n data.lineItem,\n nameof('quantity'),\n 'number',\n false,\n (updatedLineItem: unknown) => {\n data.onChangeCallback(updatedLineItem as LineItemValue);\n },\n (field: string, updatedLineItem: unknown) => {\n data.onBlurCallback(updatedLineItem as LineItemValue);\n },\n (e: KeyboardEvent) => {\n // If the user is typing in an input, we want to close all popovers, as we ideally don't\n // want to display stale data as the user updates things\n removePopover();\n },\n 'decimal-5',\n ),\n cellHorizontalAlignment: 'right',\n dataAttributes: {\n 'column-name': 'quantity',\n },\n });\n\n newRowObj.cells.push({\n cellWidth: 'sm',\n cellContent: (\n {\n const newValue = e.target.value;\n const lineItemCopy = clone(data.lineItem);\n lineItemCopy.quantityUnitOfMeasure = newValue;\n\n data.onChangeCallback(lineItemCopy);\n }}\n onBlur={(e) => {\n data.onBlurCallback(data.lineItem);\n }}\n >\n {data.unitsOfMeasureDropdownListOptions.map((currOption) => {\n return (\n \n );\n })}\n \n ),\n cellHorizontalAlignment: 'left',\n dataAttributes: {\n 'column-name': 'unit-of-measure',\n },\n });\n\n newRowObj.cells.push({\n cellTriggersBTPopover: true,\n onCellMouseEnter: setPopoverForUnitPriceCell,\n onCellMouseLeave: removePopover,\n cellWidth: 'sm',\n cellContent: getUpdatableInputElement(\n data.lineItem,\n nameof('unitPrice'),\n 'number',\n false,\n (updatedObject: unknown) => {\n data.onChangeCallback(updatedObject as LineItemValue);\n },\n (field: string, updatedLineItem: unknown) => {\n data.onBlurCallback(updatedLineItem as LineItemValue);\n },\n (e: KeyboardEvent) => {\n // If the user is typing in an input, we want to close all popovers, as we ideally don't\n // want to display stale data as the user updates things\n removePopover();\n },\n 'decimal-5',\n ),\n cellHorizontalAlignment: 'right',\n dataAttributes: {\n 'column-name': 'unit-price',\n },\n });\n }\n\n const baseEstimate = BidPackageLineItem.getBaseEstimate(\n data.lineItem.quantity,\n data.lineItem.unitPrice,\n );\n\n newRowObj.cells.push({\n cellWidth: 'fill',\n cellContent: (\n // NOTE: We show / hide the popover with the mouse events for the div inside the cell content, instead of\n // using the onCellMouseEnter / onCellMouseLeave events of the grid cell. We do this because this cell\n // is a \"fill\" width so triggering the popover from the cell can result in it being displayed far away\n // from the actual cell content, since the content is right aligned.\n {\n setDisplayedPopoverInfo({\n element: e.target as HTMLElement,\n text: '',\n title: formatNumberAsCurrencyFull(baseEstimate),\n placement: 'top',\n showCloseButton: false,\n });\n }}\n onMouseLeave={removePopover}\n >\n {formatNumberAsCurrency(baseEstimate)}\n \n ),\n cellHorizontalAlignment: 'right',\n dataAttributes: {\n 'column-name': 'base-estimate',\n },\n });\n\n return newRowObj;\n },\n [getUpdatableInputElement, setDisplayedPopoverInfo, t],\n );\n\n const getGroupedLineItemRows = useCallback(\n (\n isReadOnly: boolean,\n lineItems: LineItemValue[],\n lineItemGroupOrders: LineItemGroupOrderValue[],\n lineItemRollup1: string,\n lineItemRollup2: string,\n unitsOfMeasureDropdownListOptions: string[],\n onChangeCallback: (updatedObject: LineItemValue) => void,\n onBlurCallback: (updatedLineItem: LineItemValue) => void,\n lineItemEditCallback: (lineItemId: string) => void,\n lineItemsEditCallback: () => void,\n lineItemDeleteCallback: (lineItemId: string) => void,\n lineItemsDeleteCallback: () => void,\n globalCollapseResponseKey: string | null,\n alternateId: string | null,\n alternateName: string | null,\n ): BTGridRowPrimary[] => {\n const lineItemRows: BTGridRowPrimary[] = [];\n\n // Level 0 rows\n const level0Rows: BTGridRowPrimary[] = [];\n const groupedLineItems = groupBy(lineItems, (v) =>\n v.metadata ? v.metadata.find((m) => m.name === lineItemRollup1)?.value || '' : '',\n );\n\n Object.keys(groupedLineItems).forEach((currGroupingKey1) => {\n if (currGroupingKey1 === '') {\n for (const currLineItem of groupedLineItems[currGroupingKey1]) {\n // Level 0 line items\n level0Rows.push(\n generateGridRowForLineItem_Details({\n groupingLevel: 0,\n isReadOnly,\n isSelectable: true,\n unitsOfMeasureDropdownListOptions,\n lineItem: currLineItem,\n onBlurCallback: onBlurCallback,\n onChangeCallback: onChangeCallback,\n lineItemEditCallback: lineItemEditCallback,\n lineItemsEditCallback: lineItemsEditCallback,\n lineItemDeleteCallback: lineItemDeleteCallback,\n lineItemsDeleteCallback: lineItemsDeleteCallback,\n groupingKey1: currGroupingKey1,\n groupingKey2: null,\n globalCollapseResponseKey,\n alternateId,\n alternateName,\n }),\n );\n }\n } else {\n // Level 0 groups\n const newGroupedRow = generateGridRow_Grouped({\n id: currGroupingKey1,\n isReadOnly,\n lineItem: {\n type: 'groupedRow',\n groupingId: currGroupingKey1,\n groupingKey: currGroupingKey1,\n groupingLevel: 0,\n },\n sortableInfo: !isReadOnly\n ? {\n sortableContainerId: alternateId\n ? `${LineItemGridRowSortableContainerId}-${alternateId}`\n : LineItemGridRowSortableContainerId,\n sortableDirection: 'vertical',\n }\n : undefined,\n groupingLevel: 0,\n order:\n lineItemGroupOrders.find(\n (o) => o.groupingKey1 === currGroupingKey1 && o.groupingKey2 === null,\n )?.order ?? null,\n groupingKey1: currGroupingKey1,\n groupingKey2: null,\n globalCollapseResponseKey,\n });\n\n newGroupedRow.dataAttributes = {\n 'alternate-name': alternateName || '',\n 'line-item-description': currGroupingKey1 || '',\n 'line-item-metadata1': currGroupingKey1 || '',\n 'line-item-metadata2': '',\n 'line-item-order': newGroupedRow.groupingInfo?.order?.toString() || '',\n };\n\n newGroupedRow.cells[0].dataAttributes = {\n 'column-name': 'description',\n };\n\n newGroupedRow.cells[0].frozenOnHorizontalScroll = true;\n\n newGroupedRow.groupingInfo = {\n isGroupedRow: true,\n order: newGroupedRow.groupingInfo?.order ?? null,\n groupingLevel: newGroupedRow.groupingInfo?.groupingLevel ?? null,\n groupingKey1: newGroupedRow.groupingInfo?.groupingKey1 ?? null,\n groupingKey2: null,\n groupingParent1Info: newGroupedRow.groupingInfo?.groupingParent1Info,\n groupingParent2Info: newGroupedRow.groupingInfo?.groupingParent2Info,\n globalCollapseResponseKey,\n globalCollapseTriggerKey: null,\n };\n\n level0Rows.push(newGroupedRow);\n }\n });\n\n const sortedLevel0Rows = sortBy(level0Rows, (r) => r.groupingInfo?.order ?? 0);\n\n sortedLevel0Rows.forEach((level0Row) => {\n lineItemRows.push(level0Row);\n const groupingKey1 = level0Row.groupingInfo?.groupingKey1 ?? '';\n\n // For each level 0 group, add the children\n if (level0Row.groupingInfo?.isGroupedRow) {\n const groupedLineItems2 = groupBy(groupedLineItems[groupingKey1], (v) =>\n v.metadata ? v.metadata.find((m) => m.name === lineItemRollup2)?.value || '' : '',\n );\n\n // Level 1 rows\n const level1Rows: BTGridRowPrimary[] = [];\n Object.keys(groupedLineItems2).forEach((currGroupingKey2) => {\n if (currGroupingKey2 === '') {\n for (const currLineItem of groupedLineItems2[currGroupingKey2]) {\n // Level 1 line items\n level1Rows.push(\n generateGridRowForLineItem_Details({\n groupingLevel: 1,\n isReadOnly,\n isSelectable: true,\n unitsOfMeasureDropdownListOptions,\n lineItem: currLineItem,\n onBlurCallback: onBlurCallback,\n onChangeCallback: onChangeCallback,\n lineItemEditCallback: lineItemEditCallback,\n lineItemsEditCallback: lineItemsEditCallback,\n lineItemDeleteCallback: lineItemDeleteCallback,\n lineItemsDeleteCallback: lineItemsDeleteCallback,\n groupingParent1Info: {\n order: level0Row.groupingInfo?.order ?? -1,\n isTheLastElementOfThisParent: false, // Default to false. To be set later\n },\n groupingKey1: groupingKey1,\n groupingKey2: currGroupingKey2,\n globalCollapseResponseKey,\n alternateId,\n alternateName,\n }),\n );\n }\n } else {\n // Level 1 groups\n const newGroupedRow = generateGridRow_Grouped({\n id: `${groupingKey1}-${currGroupingKey2}`,\n isReadOnly,\n lineItem: {\n type: 'groupedRow',\n groupingId: `${groupingKey1}-${currGroupingKey2}`,\n groupingKey: currGroupingKey2,\n groupingLevel: 1,\n },\n sortableInfo: !isReadOnly\n ? {\n sortableContainerId: alternateId\n ? `${LineItemGridRowSortableContainerId}-${alternateId}`\n : LineItemGridRowSortableContainerId,\n sortableDirection: 'vertical',\n }\n : undefined,\n groupingLevel: 1,\n order:\n lineItemGroupOrders.find(\n (o) => o.groupingKey1 === groupingKey1 && o.groupingKey2 === currGroupingKey2,\n )?.order ?? null,\n groupingKey1: groupingKey1,\n groupingKey2: currGroupingKey2,\n groupingParent1Info: {\n order: level0Row.groupingInfo?.order ?? -1,\n isTheLastElementOfThisParent: false, // Default to false. To be set later\n },\n globalCollapseResponseKey,\n });\n\n newGroupedRow.dataAttributes = {\n 'alternate-name': alternateName || '',\n 'line-item-description': currGroupingKey2 || '',\n 'line-item-metadata1': groupingKey1 || '',\n 'line-item-metadata2': currGroupingKey2 || '',\n 'line-item-order': newGroupedRow.groupingInfo?.order?.toString() || '',\n };\n\n newGroupedRow.cells[0].dataAttributes = {\n 'column-name': 'description',\n };\n\n newGroupedRow.cells[0].frozenOnHorizontalScroll = true;\n\n newGroupedRow.groupingInfo = {\n isGroupedRow: true,\n order: newGroupedRow.groupingInfo?.order ?? null,\n groupingLevel: newGroupedRow.groupingInfo?.groupingLevel ?? null,\n groupingKey1: newGroupedRow.groupingInfo?.groupingKey1 ?? null,\n groupingKey2: newGroupedRow.groupingInfo?.groupingKey2 ?? null,\n groupingParent1Info: newGroupedRow.groupingInfo?.groupingParent1Info,\n groupingParent2Info: newGroupedRow.groupingInfo?.groupingParent2Info,\n globalCollapseResponseKey:\n newGroupedRow.groupingInfo?.globalCollapseResponseKey ?? null,\n globalCollapseTriggerKey: null,\n };\n\n level1Rows.push(newGroupedRow);\n }\n });\n\n const sortedLevel1Rows = sortBy(level1Rows, (r) => r.groupingInfo?.order ?? 0);\n\n sortedLevel1Rows.forEach((level1Row, level1Index, lvl1Rows) => {\n const isCurrLevel0LastElement = level1Index === lvl1Rows.length - 1;\n level1Row.groupingInfo!.groupingParent1Info!.isTheLastElementOfThisParent = isCurrLevel0LastElement;\n lineItemRows.push(level1Row);\n\n const groupingKey2 = level1Row.groupingInfo?.groupingKey2 ?? '';\n\n // For each level 1 group, add its children\n if (level1Row.groupingInfo?.isGroupedRow) {\n // Level 2 rows\n const level2Rows: BTGridRowPrimary[] = [];\n for (const currLineItem of groupedLineItems2[groupingKey2]) {\n // Level 2 line items\n level2Rows.push(\n generateGridRowForLineItem_Details({\n groupingLevel: 2,\n isReadOnly,\n isSelectable: true,\n unitsOfMeasureDropdownListOptions,\n lineItem: currLineItem,\n onBlurCallback: onBlurCallback,\n onChangeCallback: onChangeCallback,\n lineItemEditCallback: lineItemEditCallback,\n lineItemsEditCallback: lineItemsEditCallback,\n lineItemDeleteCallback: lineItemDeleteCallback,\n lineItemsDeleteCallback: lineItemsDeleteCallback,\n groupingKey1: groupingKey1,\n groupingKey2: groupingKey2,\n groupingParent1Info: {\n order: level0Row.groupingInfo?.order ?? -1,\n isTheLastElementOfThisParent: false, // Default to false. To be set later\n },\n groupingParent2Info: {\n order: level1Row.groupingInfo?.order ?? -1,\n isTheLastElementOfThisParent: false, // Default to false. To be set later\n },\n globalCollapseResponseKey,\n alternateId,\n alternateName,\n }),\n );\n }\n\n const sortedLevel2Rows = sortBy(level2Rows, (r) => r.groupingInfo?.order ?? 0);\n\n sortedLevel2Rows.forEach((level2Row, level2Index, lvl2Rows) => {\n const isCurrLevel1LastElement = level2Index === lvl2Rows.length - 1;\n level2Row.groupingInfo!.groupingParent1Info!.isTheLastElementOfThisParent =\n isCurrLevel1LastElement && isCurrLevel0LastElement;\n level2Row.groupingInfo!.groupingParent2Info!.isTheLastElementOfThisParent = isCurrLevel1LastElement;\n lineItemRows.push(level2Row);\n });\n }\n });\n }\n });\n\n return lineItemRows;\n },\n [generateGridRowForLineItem_Details],\n );\n\n return { getGroupedLineItemRows };\n};\n\ninterface LineItemsDropdownItemsProps {\n alternateId: string | null;\n lineItemsEditCallback: () => void;\n lineItemsDeleteCallback: () => void;\n}\n\n// NOTE: We break this out into its own component so we can subscribe to the selected line items mapping\n// observable for a specific alternate ID. Doing so is impossible if this code is inside of the functions above.\nconst LineItemsDropdownItems: React.FC = ({\n alternateId,\n lineItemsEditCallback,\n lineItemsDeleteCallback,\n}) => {\n const { t } = useTranslation();\n\n const [lineItemsAreSelected, setLineItemsAreSelected] = useState(false);\n\n const { selectedLineItemsMappings$ } = useBidPackagePageContext();\n\n useEffect(() => {\n const allSubscriptions = new Subscription();\n allSubscriptions.add(\n selectedLineItemsMappings$.subscribe((v) => {\n setLineItemsAreSelected((v[alternateId || '']?.length ?? 0) > 0);\n }),\n );\n\n return () => {\n allSubscriptions.unsubscribe();\n };\n }, [alternateId, selectedLineItemsMappings$]);\n\n return (\n <>\n {lineItemsAreSelected ? (\n <>\n \n\n {\n lineItemsEditCallback();\n }}\n icon=\"edit\"\n text={t('general:editSelected')}\n />\n\n {\n lineItemsDeleteCallback();\n }}\n icon=\"trash\"\n text={t('general:deleteSelected')}\n />\n \n ) : (\n <>\n )}\n \n );\n};\n\nexport default useLineItemsHelpers;\n","import { useCallback, useContext } from 'react';\r\nimport { Alternate } from '../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\r\nimport { BidPackageLineItem } from '../../../../../classes/odata/bid-package-line-item';\r\nimport { BidPackageLineItemBid } from '../../../../../classes/odata/bid-package-line-item-bid';\r\nimport { BidPackageLineItemGroupOrder } from '../../../../../classes/odata/bid-package-line-item-group-order';\r\nimport { BidPackageLineItemRollupBid } from '../../../../../classes/odata/bid-package-line-item-rollup-bid';\r\nimport { Project } from '../../../../../classes/odata/project';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n normalizeNullOrUndefined,\r\n} from '../../../../../utils/general';\r\nimport { areTrimmedStringsEqual } from '../../../../../utils/strings';\r\nimport { BTPopoverContext } from '../../../../common-page-components/popover/BTPopoverContext';\r\nimport { BidClassificationTypes } from '../../../../enums/bid-package-enums';\r\nimport useBidPackagePageContext from '../BidPackagePageContext';\r\nimport useBidderHelpers from './helpers/useBidderHelpers';\r\nimport useLineItemsHelpers from './helpers/useLineItemsHelpers';\r\n\r\ninterface GenerateBidPackage_LineItems_GridSection_Params {\r\n gridSectionId: string;\r\n isReadOnly: boolean;\r\n bidPackage: BidPackage;\r\n projectInfo: Project;\r\n alternate: Alternate | null;\r\n lineItems: BidPackageLineItem[];\r\n lineItemGroupOrders: BidPackageLineItemGroupOrder[];\r\n lineItemRollupBids: BidPackageLineItemRollupBid[];\r\n unitsOfMeasureDropdownListOptions: string[];\r\n globalCollapseResponseKey: string | null;\r\n}\r\n\r\ninterface ReturnValue {\r\n generateBidPackage_LineItems_GridSection: (\r\n data: GenerateBidPackage_LineItems_GridSection_Params,\r\n ) => BTGridSection | null;\r\n}\r\n\r\nconst useBidPackageGrid_LineItems = (): ReturnValue => {\r\n const {\r\n lineItem_Change,\r\n lineItem_Blur,\r\n lineItem_Delete,\r\n lineItems_Delete,\r\n lineItem_Edit,\r\n lineItems_Edit,\r\n lineItemBid_Change,\r\n lineItemBid_Blur,\r\n lineItemBid_Focus,\r\n lineItemRollupBid_Change,\r\n lineItemRollupBid_Blur,\r\n } = useBidPackagePageContext();\r\n\r\n const { getGroupedLineItemRows } = useLineItemsHelpers();\r\n\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const { getInputElementForBidField } = useBidderHelpers();\r\n\r\n const generateSubGrid_LineItems = useCallback(\r\n (\r\n gridSectionId: string,\r\n isReadOnly: boolean,\r\n gridSectionTestId: string,\r\n alternate: Alternate | null,\r\n lineItems: LineItemValue[],\r\n lineItemGroupOrders: LineItemGroupOrderValue[],\r\n projectInfo: Project,\r\n unitsOfMeasureDropdownListOptions: string[],\r\n globalCollapseResponseKey: string | null,\r\n ): BTSubGrid => {\r\n const lineItemRows: BTGridRowPrimary[] = getGroupedLineItemRows(\r\n isReadOnly,\r\n lineItems,\r\n lineItemGroupOrders,\r\n projectInfo.lineItemRollup1 || '',\r\n projectInfo.lineItemRollup2 || '',\r\n unitsOfMeasureDropdownListOptions,\r\n (updatedObject: unknown) => {\r\n lineItem_Change(updatedObject as LineItemValue);\r\n },\r\n (updatedLineItem: LineItemValue) => lineItem_Blur(updatedLineItem),\r\n (lineItemId: string) => {\r\n lineItem_Edit(lineItemId);\r\n },\r\n () => {\r\n lineItems_Edit(alternate?.id ?? null);\r\n },\r\n (lineItemId: string) => {\r\n lineItem_Delete(lineItemId);\r\n },\r\n () => {\r\n lineItems_Delete(alternate?.id ?? null);\r\n },\r\n globalCollapseResponseKey,\r\n alternate?.id ?? null,\r\n alternate?.name ?? null,\r\n );\r\n\r\n // Update the styling of the line items rows\r\n lineItemRows.forEach((currLineItemRow, i) => {\r\n if (isReadOnly) {\r\n currLineItemRow.selectableCellAdditionalStyles = ['border-left'];\r\n }\r\n\r\n // Add a right border to the last cell\r\n currLineItemRow.cells.forEach((currCell, m) => {\r\n if (m === currLineItemRow.cells.length - 1) {\r\n currCell.cellAdditionalStyles = (currCell.cellAdditionalStyles || []).concat([\r\n 'border-right',\r\n ]);\r\n }\r\n });\r\n });\r\n\r\n return {\r\n id: `${gridSectionId} - c66dd2e8-0a1c-4573-a497-5a0e6354a8a0`,\r\n testId: `${gridSectionTestId}_PrimarySubGrid`,\r\n auxiliaryRows: [],\r\n rows: lineItemRows,\r\n addLeftPadding: false,\r\n };\r\n },\r\n [\r\n getGroupedLineItemRows,\r\n lineItem_Blur,\r\n lineItem_Change,\r\n lineItem_Delete,\r\n lineItem_Edit,\r\n lineItems_Delete,\r\n lineItems_Edit,\r\n ],\r\n );\r\n\r\n const generateSubGrids_Bidders = useCallback(\r\n (\r\n gridSectionId: string,\r\n gridSectionTestId: string,\r\n bidPackage: BidPackage,\r\n alternate: Alternate | null,\r\n lineItems: BidPackageLineItem[],\r\n lineItemRollupBids: BidPackageLineItemRollupBid[],\r\n lineItemRows: BTGridRowPrimary[],\r\n isReadOnly: boolean,\r\n ): BTSubGrid[] => {\r\n const returnValue: BTSubGrid[] = [];\r\n\r\n bidPackage.bidders.forEach((currBidder) => {\r\n const isSelectedBidder = currBidder.id === bidPackage.selectedBidderId;\r\n\r\n const bidderRows: BTGridRowBase[] = [];\r\n\r\n // NOTE: These line item grid rows correspond to individual line items or grouped line item rows\r\n lineItemRows.forEach((currLineItemGridRow) => {\r\n const currLineItemGridRowIsGroupedRow =\r\n currLineItemGridRow.groupingInfo?.isGroupedRow === true;\r\n\r\n let lineItem_Value1: number | null = null;\r\n let lineItem_Value2: number | null = null;\r\n let lineItem_PlaceholderValue: string | null = null;\r\n let lineItem_PlaceholderValueFull: string | null = null;\r\n\r\n let matchingBid: BidPackageLineItemBid | null = null;\r\n\r\n let matchingRollupBid: BidPackageLineItemRollupBid | null = null;\r\n\r\n let matchingLineItem: BidPackageLineItem | null = null;\r\n\r\n let parentRollupBidExists = false;\r\n\r\n // If the current line item grid row is a line item row\r\n if (!currLineItemGridRowIsGroupedRow) {\r\n // In the case of an individual line item, the grid row's ID will match the line item's ID\r\n const currLineItemRowId = currLineItemGridRow.id;\r\n\r\n matchingLineItem = lineItems.find((v) => v.id === currLineItemRowId) ?? null;\r\n\r\n if (matchingLineItem) {\r\n matchingBid = matchingLineItem.bids.find((v) => v.bidderId === currBidder.id) || null;\r\n\r\n if (matchingBid) {\r\n lineItem_Value1 = matchingBid.price !== undefined ? matchingBid.price : null;\r\n lineItem_Value2 = matchingBid.classification || null;\r\n\r\n // Set a placeholder value for \"missing scope\" bids without a value defined\r\n if (\r\n matchingBid.classification === BidClassificationTypes.MissingScope &&\r\n normalizeNullOrUndefined(matchingBid.price) === null\r\n ) {\r\n lineItem_PlaceholderValue = formatNumberAsCurrency(\r\n bidPackage.calculateLineItemBidValue(matchingLineItem, currBidder.id!),\r\n );\r\n lineItem_PlaceholderValueFull = formatNumberAsCurrencyFull(\r\n bidPackage.calculateLineItemBidValue(matchingLineItem, currBidder.id!),\r\n );\r\n }\r\n }\r\n }\r\n } else {\r\n // If the line item grid row is a line item grouping row, populate any rollup bids for the current bidder.\r\n matchingRollupBid =\r\n lineItemRollupBids.find(\r\n (v) =>\r\n v.bidderId === currBidder.id &&\r\n areTrimmedStringsEqual(\r\n v.metadataValue1 || '',\r\n currLineItemGridRow.groupingInfo?.groupingKey1 || '',\r\n ) &&\r\n areTrimmedStringsEqual(\r\n v.metadataValue2 || '',\r\n currLineItemGridRow.groupingInfo?.groupingKey2 || '',\r\n ),\r\n ) || null;\r\n\r\n if (matchingRollupBid) {\r\n lineItem_Value1 =\r\n matchingRollupBid.bidValue !== undefined ? matchingRollupBid.bidValue : null;\r\n }\r\n\r\n // We no longer allow grouping row rollup bids if a \"parent\" rollup bid exists. If one is found, set parentRollupBidExists to true.\r\n parentRollupBidExists =\r\n lineItemRollupBids\r\n .filter((v) => v.bidValue !== undefined)\r\n .find((v) => {\r\n // If the current grouped row has both metadata properties set (i.e. classification 2 grouping row),\r\n // look for a parent rollup bid (i.e. one that matches just the first grouping key).\r\n if (\r\n (currLineItemGridRow.groupingInfo?.groupingKey1 || '') &&\r\n (currLineItemGridRow.groupingInfo?.groupingKey2 || '')\r\n ) {\r\n return (\r\n v.bidderId === currBidder.id &&\r\n !v.metadataValue2 &&\r\n (!v.metadataValue1 ||\r\n areTrimmedStringsEqual(\r\n v.metadataValue1,\r\n currLineItemGridRow.groupingInfo?.groupingKey1,\r\n ))\r\n );\r\n }\r\n // If the current grouped row has just the first metadata property set (i.e. classification 1 grouping row),\r\n // look for a parent rollup bid (i.e. one without any metadata properties).\r\n else if (\r\n (currLineItemGridRow.groupingInfo?.groupingKey1 || '') &&\r\n !(currLineItemGridRow.groupingInfo?.groupingKey2 || '')\r\n ) {\r\n return v.bidderId === currBidder.id && !v.metadataValue1 && !v.metadataValue2;\r\n }\r\n return false;\r\n }) !== undefined;\r\n }\r\n\r\n const lineItemHasPriceOrPlaceholderValue =\r\n typeof lineItem_Value1 === 'number' || lineItem_PlaceholderValueFull;\r\n\r\n bidderRows.push({\r\n id: `${gridSectionId} - Bidder Row - ${currLineItemGridRow.id}`,\r\n isPrimaryGridRow: false,\r\n isHoverable: true,\r\n dataAttributes: {\r\n 'alternate-name': alternate?.name || '',\r\n 'line-item-description': currLineItemGridRowIsGroupedRow\r\n ? (currLineItemGridRow.groupingInfo?.groupingKey2 ??\r\n currLineItemGridRow.groupingInfo?.groupingKey1) ||\r\n ''\r\n : matchingLineItem!.description || '',\r\n 'line-item-metadata1': currLineItemGridRow.groupingInfo?.groupingKey1 || '',\r\n 'line-item-metadata2': currLineItemGridRow.groupingInfo?.groupingKey2 || '',\r\n 'bidder-name': currBidder.companyName || '',\r\n },\r\n cells: [\r\n {\r\n cellTriggersBTPopover: lineItemHasPriceOrPlaceholderValue ? true : false,\r\n onCellMouseEnter: (e) => {\r\n if (lineItemHasPriceOrPlaceholderValue) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title:\r\n lineItem_PlaceholderValueFull ||\r\n formatNumberAsCurrencyFull(lineItem_Value1 || 0),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n },\r\n onCellMouseLeave: () => {\r\n if (lineItemHasPriceOrPlaceholderValue) {\r\n setDisplayedPopoverInfo(null);\r\n }\r\n },\r\n cellContent: currLineItemGridRowIsGroupedRow\r\n ? getInputElementForBidField({\r\n inputType: 'number',\r\n isLineItem: true,\r\n price: lineItem_Value1,\r\n value: undefined,\r\n classification: undefined,\r\n placeholder: lineItem_PlaceholderValue || '',\r\n isDisabled: isReadOnly || parentRollupBidExists,\r\n onBidFocusCallback: () => {\r\n lineItemBid_Focus({\r\n bidderId: currBidder.id!,\r\n bidPackageLineItemId: currLineItemGridRow.id,\r\n });\r\n },\r\n onBidChangeCallback: (bidderValue: BidderValue) => {\r\n if (currLineItemGridRow?.groupingInfo?.groupingKey1) {\r\n lineItemRollupBid_Change({\r\n // Add some extra info to the event, then bubble it up\r\n ...bidderValue,\r\n bidId: matchingBid?.id || undefined,\r\n bidderId: currBidder.id || '',\r\n alternateId: alternate?.id || undefined,\r\n lineItemRollup1:\r\n currLineItemGridRow?.groupingInfo?.groupingKey1 || null,\r\n lineItemRollup2:\r\n currLineItemGridRow?.groupingInfo?.groupingKey2 || null,\r\n });\r\n }\r\n },\r\n onBidBlurCallback: (bidderValue: BidderValue) => {\r\n if (currLineItemGridRow.groupingInfo?.groupingKey1) {\r\n // Add some extra info to the event, then bubble it up\r\n lineItemRollupBid_Blur({\r\n ...bidderValue,\r\n bidId: matchingBid?.id || undefined,\r\n bidderId: currBidder.id || '',\r\n alternateId: alternate?.id || undefined,\r\n lineItemRollup1:\r\n currLineItemGridRow?.groupingInfo?.groupingKey1 || null,\r\n lineItemRollup2:\r\n currLineItemGridRow?.groupingInfo?.groupingKey2 || null,\r\n });\r\n }\r\n },\r\n })\r\n : getInputElementForBidField({\r\n inputType: 'combo',\r\n isLineItem: true,\r\n price: lineItem_Value1,\r\n value: undefined,\r\n classification: lineItem_Value2 || undefined,\r\n placeholder: lineItem_PlaceholderValue || '',\r\n isDisabled: isReadOnly,\r\n onBidFocusCallback: () => {\r\n lineItemBid_Focus({\r\n bidderId: currBidder.id!,\r\n bidPackageLineItemId: currLineItemGridRow.id,\r\n });\r\n },\r\n onBidChangeCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n lineItemBid_Change({\r\n ...bidderValue,\r\n bidId: matchingBid?.id || undefined,\r\n bidderId: currBidder.id,\r\n bidPackageLineItemId: currLineItemGridRow.id,\r\n });\r\n },\r\n onBidBlurCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n lineItemBid_Blur({\r\n ...bidderValue,\r\n bidId: matchingBid?.id || undefined,\r\n bidderId: currBidder.id,\r\n bidPackageLineItemId: currLineItemGridRow.id,\r\n });\r\n },\r\n }),\r\n cellWidth: 'md',\r\n cellBackgroundColor: isSelectedBidder ? 'blue' : 'none',\r\n cellAdditionalStyles: ['border-sides'],\r\n dataAttributes: {\r\n 'alternate-name': alternate?.name || '',\r\n 'line-item-description': currLineItemGridRowIsGroupedRow\r\n ? currLineItemGridRow?.groupingInfo?.groupingKey2 ??\r\n currLineItemGridRow?.groupingInfo?.groupingKey1 ??\r\n ''\r\n : matchingLineItem!.description || '',\r\n 'line-item-metadata1': currLineItemGridRow?.groupingInfo?.groupingKey1 || '',\r\n 'line-item-metadata2': currLineItemGridRow?.groupingInfo?.groupingKey2 || '',\r\n 'bidder-name': currBidder.companyName || '',\r\n },\r\n },\r\n ],\r\n });\r\n });\r\n\r\n const testId = `${gridSectionTestId}_SubGrid_${currBidder!.companyName!.replace(\r\n / /g,\r\n '_',\r\n )}`;\r\n\r\n returnValue.push({\r\n id: `Bidder SubGrid - Line Items - ${gridSectionId} - ${testId}}`,\r\n testId: testId,\r\n auxiliaryRows: [],\r\n rows: bidderRows,\r\n addLeftPadding: true,\r\n });\r\n });\r\n\r\n return returnValue;\r\n },\r\n [\r\n getInputElementForBidField,\r\n lineItemBid_Blur,\r\n lineItemBid_Change,\r\n lineItemBid_Focus,\r\n lineItemRollupBid_Blur,\r\n lineItemRollupBid_Change,\r\n setDisplayedPopoverInfo,\r\n ],\r\n );\r\n\r\n const generateBidPackage_LineItems_GridSection = useCallback(\r\n (data: GenerateBidPackage_LineItems_GridSection_Params): BTGridSection | null => {\r\n if (!data.bidPackage) {\r\n return null;\r\n }\r\n\r\n const gridSectionTestId =\r\n 'BidPackagePage_GridSection_LineItems' +\r\n (data.alternate ? `_${data.alternate!.name!.replace(/ /g, '_')}` : '');\r\n\r\n const lineItemsSubGrid = generateSubGrid_LineItems(\r\n data.gridSectionId,\r\n data.isReadOnly,\r\n gridSectionTestId,\r\n data.alternate,\r\n data.lineItems,\r\n data.lineItemGroupOrders,\r\n data.projectInfo,\r\n data.unitsOfMeasureDropdownListOptions,\r\n data.globalCollapseResponseKey,\r\n );\r\n\r\n const biddersSubGrids = generateSubGrids_Bidders(\r\n data.gridSectionId,\r\n gridSectionTestId,\r\n data.bidPackage,\r\n data.alternate,\r\n data.lineItems,\r\n data.lineItemRollupBids,\r\n lineItemsSubGrid!.rows as BTGridRowPrimary[],\r\n data.isReadOnly,\r\n );\r\n\r\n return {\r\n id: data.gridSectionId,\r\n primaryGrid: lineItemsSubGrid!,\r\n secondaryGrids: biddersSubGrids,\r\n testId: gridSectionTestId,\r\n };\r\n },\r\n [generateSubGrid_LineItems, generateSubGrids_Bidders],\r\n );\r\n\r\n return { generateBidPackage_LineItems_GridSection };\r\n};\r\n\r\nexport default useBidPackageGrid_LineItems;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport Big from 'big.js';\r\nimport React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Dropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reactstrap';\r\nimport { Subscription } from 'rxjs';\r\nimport { Alternate } from '../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\r\nimport BidPackageConstants from '../../../../../constants/bid-package';\r\nimport {\r\n generateEmptyGridRowWithEmptyCells_Base,\r\n generateEmptyGridRowWithNoCells_Primary,\r\n} from '../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n normalizeNullOrUndefined,\r\n} from '../../../../../utils/general';\r\nimport BTIconButtonToggle from '../../../../common-page-components/controls/icon-button-toggle/BTIconButtonToggle';\r\nimport { BTPopoverContext } from '../../../../common-page-components/popover/BTPopoverContext';\r\nimport { GlobalCollapseResponseKeyPrefix } from '../BidPackagePage';\r\nimport useBidPackagePageContext from '../BidPackagePageContext';\r\nimport useBidderHelpers from './helpers/useBidderHelpers';\r\n\r\ninterface GenerateLineItemsAlternatesGridSectionHeaderRows_Params {\r\n bidPackage: BidPackage;\r\n gridSectionId: string;\r\n alternate: Alternate;\r\n isReadOnly: boolean;\r\n allLineItemsCount: number;\r\n lineItemsCountForSection: number;\r\n}\r\n\r\ninterface ReturnValue {\r\n generateLineItemsAlternatesGridSectionHeaderRows: (\r\n data: GenerateLineItemsAlternatesGridSectionHeaderRows_Params,\r\n ) => BTGridRowSet;\r\n generateLineItemsAlternatesGridSectionHeaderRowExtensions: (\r\n data: GenerateLineItemsAlternatesGridSectionHeaderRows_Params,\r\n ) => BTGridRowSet;\r\n}\r\n\r\nconst useBidPackageGrid_LineItems_Alternates = (): ReturnValue => {\r\n const {\r\n lineItems_Add,\r\n lineItemRollupBid_Blur,\r\n lineItemRollupBid_Change,\r\n } = useBidPackagePageContext();\r\n\r\n const { t } = useTranslation();\r\n\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const { getInputElementForBidField } = useBidderHelpers();\r\n\r\n // Returns the an array that includes the primary header row and rows for each bidder\r\n const generateLineItemsAlternatesGridSectionHeaderRows = useCallback(\r\n (data: GenerateLineItemsAlternatesGridSectionHeaderRows_Params): BTGridRowSet => {\r\n const headerRow: BTGridRowPrimary = {\r\n ...generateEmptyGridRowWithNoCells_Primary(\r\n `${data.gridSectionId} - header - d78cd184-0c92-4916-9301-dcce07c73047`,\r\n ),\r\n groupingLevel: null,\r\n isCollapsibleTrigger: true,\r\n isHoverable: false,\r\n isSelectable: false,\r\n showBottomBorder: false,\r\n groupingInfo: {\r\n order: null,\r\n isGroupedRow: false,\r\n groupingKey1: null,\r\n groupingKey2: null,\r\n groupingLevel: null,\r\n globalCollapseResponseKey: null,\r\n globalCollapseTriggerKey: `${GlobalCollapseResponseKeyPrefix}${data.alternate.id}`,\r\n },\r\n cells: [\r\n {\r\n cellWidth: 'fill',\r\n cellVerticalAlignment: 'bottom',\r\n cellContent: (\r\n
    \r\n

    \r\n \r\n {`${data.alternate.name}${\r\n !data.alternate.enabled ? ` (${t('general:notIncluded')})` : ''\r\n }`}\r\n\r\n \r\n \r\n \r\n \r\n\r\n {data.isReadOnly ? (\r\n <>\r\n ) : (\r\n ) => {\r\n // Canceling the event from triggering the collapse\r\n e.preventDefault();\r\n e.stopPropagation();\r\n lineItems_Add(data.alternate.name || null);\r\n }}\r\n value={false}\r\n disabled={data.isReadOnly}\r\n />\r\n )}\r\n

    \r\n\r\n
    \r\n {data.allLineItemsCount >=\r\n BidPackageConstants.BID_PACKAGE_LINEITEMS_PERFORMANCE_THRESHOLD ? (\r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {data.lineItemsCountForSection > 0 ? (\r\n \r\n {data.lineItemsCountForSection}\r\n
    \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n \r\n ),\r\n cellAdditionalStyles: [\r\n 'border-sides',\r\n 'border-top',\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n 'padding-bottom-none',\r\n ],\r\n cellAdditionalCollapseStyles: [\r\n 'border-bottom',\r\n 'border-rounded-bottom-left',\r\n 'border-rounded-bottom-right',\r\n ],\r\n },\r\n ],\r\n collapsibleIconJSXElementFactory,\r\n };\r\n\r\n const secondaryGridRows: BTGridRowBase[] = [];\r\n\r\n if ((data.bidPackage?.bidders?.length || 0) > 0) {\r\n data.bidPackage.bidders.forEach((currBidder) => {\r\n const rollupBidValue =\r\n BidPackage.getLineItemRollupBids(\r\n data.bidPackage.lineItemRollupBids,\r\n data.alternate.id as string,\r\n ).find((v) => v.bidderId === currBidder.id && !v.metadataValue1 && !v.metadataValue2)\r\n ?.bidValue || null;\r\n\r\n const isSelectedBidder = currBidder.id === data.bidPackage.selectedBidderId;\r\n\r\n secondaryGridRows.push({\r\n ...generateEmptyGridRowWithEmptyCells_Base(\r\n `${data.gridSectionId} - ${currBidder.id} - header - 100e82dd-144d-4777-a032-416317c511f1`,\r\n 1,\r\n 'lg',\r\n ),\r\n showBottomBorder: true,\r\n cells: [\r\n {\r\n cellTriggersBTPopover: (rollupBidValue ?? 0) > 0,\r\n onCellMouseEnter: (e) => {\r\n if (rollupBidValue) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(rollupBidValue || 0),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n },\r\n onCellMouseLeave: () => {\r\n if (rollupBidValue) {\r\n setDisplayedPopoverInfo(null);\r\n }\r\n },\r\n cellContent: getInputElementForBidField({\r\n inputType: 'number',\r\n isLineItem: false,\r\n price: rollupBidValue,\r\n value: undefined,\r\n classification: undefined,\r\n placeholder: undefined,\r\n isDisabled: data.isReadOnly,\r\n onBidChangeCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n lineItemRollupBid_Change({\r\n bidderId: currBidder.id || '',\r\n alternateId: data.alternate.id,\r\n lineItemRollup1: null,\r\n lineItemRollup2: null,\r\n price: bidderValue.price,\r\n classification: undefined,\r\n value: undefined,\r\n });\r\n },\r\n onBidBlurCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n lineItemRollupBid_Blur({\r\n bidderId: currBidder.id || '',\r\n alternateId: data.alternate.id,\r\n lineItemRollup1: null,\r\n lineItemRollup2: null,\r\n price: bidderValue.price,\r\n classification: undefined,\r\n value: undefined,\r\n });\r\n },\r\n }),\r\n cellWidth: 'md',\r\n cellBackgroundColor: isSelectedBidder ? 'blue' : 'none',\r\n cellAdditionalStyles: ['border-sides'],\r\n dataAttributes: {\r\n 'alternate-name': data.alternate.name!,\r\n 'line-item-description': '',\r\n 'line-item-metadata1': '',\r\n 'line-item-metadata2': '',\r\n 'bidder-name': currBidder.companyName || '',\r\n },\r\n },\r\n ],\r\n });\r\n });\r\n }\r\n\r\n const returnValue: BTGridRowSet = {\r\n primaryRow: headerRow,\r\n secondaryGridRows: secondaryGridRows,\r\n };\r\n\r\n return returnValue;\r\n },\r\n [\r\n getInputElementForBidField,\r\n lineItemRollupBid_Blur,\r\n lineItemRollupBid_Change,\r\n lineItems_Add,\r\n setDisplayedPopoverInfo,\r\n t,\r\n ],\r\n );\r\n\r\n // Returns the an array that includes the secondary header row and rows for each bidder\r\n const generateLineItemsAlternatesGridSectionHeaderRowExtensions = useCallback(\r\n (data: GenerateLineItemsAlternatesGridSectionHeaderRows_Params): BTGridRowSet => {\r\n const headerRow: BTGridRowPrimary = {\r\n ...generateEmptyGridRowWithNoCells_Primary(\r\n `${data.gridSectionId} - line item column header - 5b57fe8a-aa1D-4c80-9e4e-a9c442ae5714`,\r\n ),\r\n groupingLevel: null,\r\n isCollapsibleTrigger: false,\r\n collapseDirection: null,\r\n isHoverable: false,\r\n showBottomBorder: true,\r\n isSelectable: false,\r\n cells: [\r\n // This cell is used to align with drag handles\r\n {\r\n cellWidth: data.isReadOnly ? 'none' : 'xs',\r\n cellContent:
    ,\r\n cellVerticalAlignment: 'bottom',\r\n cellAdditionalStyles: ['border-left'],\r\n },\r\n {\r\n cellWidth: data.isReadOnly ? 'none' : 'xs',\r\n cellContent: ,\r\n cellVerticalAlignment: 'bottom',\r\n },\r\n {\r\n cellWidth: 'xl',\r\n cellVerticalAlignment: 'bottom',\r\n cellContent:\r\n data.lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n },\r\n {\r\n cellWidth: 'sm',\r\n cellContent:\r\n data.lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n cellVerticalAlignment: 'bottom',\r\n cellHorizontalAlignment: 'right',\r\n },\r\n {\r\n cellWidth: 'sm',\r\n cellContent:\r\n data.lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n cellVerticalAlignment: 'bottom',\r\n cellHorizontalAlignment: 'left',\r\n },\r\n {\r\n cellWidth: 'sm',\r\n cellContent:\r\n data.lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n cellVerticalAlignment: 'bottom',\r\n cellHorizontalAlignment: 'right',\r\n },\r\n {\r\n cellWidth: 'fill',\r\n cellContent:\r\n data.lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n cellVerticalAlignment: 'bottom',\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-right'],\r\n },\r\n ],\r\n };\r\n\r\n const secondaryGridRows: BTGridRowBase[] = [];\r\n\r\n if ((data.bidPackage?.bidders?.length || 0) > 0) {\r\n data.bidPackage.bidders.forEach((currBidder) => {\r\n const isSelectedBidder = currBidder.id === data.bidPackage.selectedBidderId;\r\n\r\n // Calculate the total\r\n const lineItems = data.bidPackage.getLineItems(data.alternate?.id || null);\r\n\r\n let totalsValue: Big;\r\n\r\n // NOTE: For alternates that are not enabled, we show a total of 0\r\n if (data.bidPackage.isGeneralCondition && data.alternate && !data.alternate.enabled) {\r\n totalsValue = new Big(0);\r\n } else {\r\n const lineItemsValue = lineItems\r\n .map((li) => data.bidPackage.calculateLineItemBidValue(li, currBidder.id!))\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n const adjustmentBidValue = data.bidPackage.adjustments\r\n .filter(\r\n (v) =>\r\n v.bidderId === currBidder.id &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(data.alternate.id),\r\n )\r\n .map((v) => v.value || 0)\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n const lineItemRollupBidsValue = data.bidPackage.lineItemRollupBids\r\n .filter(\r\n (v) =>\r\n v.bidderId === currBidder.id &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(data.alternate.id),\r\n )\r\n .map((v) => v.bidValue || 0)\r\n .reduce((sum, curr) => sum.add(curr), new Big(0));\r\n\r\n // NOTE: Requirement fulfillments do not apply to alternates\r\n totalsValue = lineItemsValue.add(adjustmentBidValue).add(lineItemRollupBidsValue);\r\n }\r\n\r\n const formattedTotalsValue = formatNumberAsCurrency(totalsValue);\r\n const formattedTotalsFullValue = formatNumberAsCurrencyFull(totalsValue);\r\n\r\n secondaryGridRows.push({\r\n ...generateEmptyGridRowWithEmptyCells_Base(\r\n `${data.gridSectionId} - ${currBidder.id} - line item column header - 014d3abe-70dc-4729-8b00-4818f94c6d3f`,\r\n 1,\r\n 'md',\r\n ),\r\n cells: [\r\n {\r\n cellTriggersBTPopover: formattedTotalsFullValue ? true : false,\r\n onCellMouseEnter: (e) => {\r\n if (formattedTotalsFullValue) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formattedTotalsFullValue,\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n },\r\n onCellMouseLeave: () => {\r\n if (formattedTotalsFullValue) {\r\n setDisplayedPopoverInfo(null);\r\n }\r\n },\r\n cellContent: <>,\r\n cellContentWhenCollapsed:
    {formattedTotalsValue}
    ,\r\n cellHorizontalAlignment: 'right',\r\n cellWidth: 'md',\r\n cellBackgroundColor: isSelectedBidder ? 'blue' : 'none',\r\n cellAdditionalStyles: [\r\n 'border-sides',\r\n 'border-top',\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n ],\r\n cellAdditionalCollapseStyles: [\r\n 'border-bottom',\r\n 'border-rounded-bottom-left',\r\n 'border-rounded-bottom-right',\r\n ],\r\n },\r\n ],\r\n });\r\n });\r\n }\r\n\r\n const returnValue: BTGridRowSet = {\r\n primaryRow: headerRow,\r\n secondaryGridRows: secondaryGridRows,\r\n };\r\n\r\n return returnValue;\r\n },\r\n [t, setDisplayedPopoverInfo],\r\n );\r\n\r\n return {\r\n generateLineItemsAlternatesGridSectionHeaderRows,\r\n generateLineItemsAlternatesGridSectionHeaderRowExtensions,\r\n };\r\n};\r\n\r\ninterface Props {\r\n alternateId: string;\r\n}\r\n\r\n// NOTE: We create a new component for the alternate line items header because it needs to subscribe to data for\r\n// a particular alternate ID in order to show the \"hamburger\" menu icon when needed.\r\n// Since we call the hooks above to generate alternates JSX multiple times, we have to move state into a component\r\n// one level down (this one) in order to handle showing / hiding the menu icon.\r\nconst AlternateLineItemsHeader: React.FC = ({ alternateId }) => {\r\n const { t } = useTranslation();\r\n\r\n const { lineItems_Edit, lineItems_Delete } = useBidPackagePageContext();\r\n\r\n const [dropdownMenuIconIsDisplayed, setDropdownMenuIconIsDisplayed] = useState(false);\r\n\r\n const [lineItemsActionDropdownIsOpen, setLineItemsActionDropdownIsOpen] = useState(\r\n false,\r\n );\r\n\r\n const { selectedLineItemsMappings$ } = useBidPackagePageContext();\r\n\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n selectedLineItemsMappings$.subscribe((lineItemMappings) => {\r\n setDropdownMenuIconIsDisplayed((lineItemMappings[alternateId]?.length || 0) > 0);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [alternateId, selectedLineItemsMappings$]);\r\n\r\n return useMemo(() => {\r\n return (\r\n
    \r\n {dropdownMenuIconIsDisplayed ? (\r\n {\r\n setLineItemsActionDropdownIsOpen((v) => !v);\r\n }}\r\n direction={'left'}\r\n >\r\n \r\n \r\n \r\n\r\n \r\n lineItems_Edit(alternateId)}>\r\n \r\n {t('general:edit')}\r\n \r\n lineItems_Delete(alternateId)}>\r\n \r\n {t('general:delete')}\r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n );\r\n }, [\r\n alternateId,\r\n dropdownMenuIconIsDisplayed,\r\n lineItemsActionDropdownIsOpen,\r\n lineItems_Delete,\r\n lineItems_Edit,\r\n t,\r\n ]);\r\n};\r\n\r\nconst collapsibleIconJSXElementFactory = (element: JSX.Element): JSX.Element =>

    {element}

    ;\r\n\r\nexport default useBidPackageGrid_LineItems_Alternates;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Bidder, BidderStatus } from '../../../../../classes/odata/bidder';\nimport './BidderStatusDropdown.scss';\n\ninterface Props {\n bidder: Bidder;\n isSelectedBidder: boolean;\n isReadOnly: boolean;\n onChange: (bidder: Bidder, status: BidderStatus) => Promise;\n}\n\nconst bidderStatusToClassNameMap = {\n [BidderStatus.RequestCreated]: 'requestCreated',\n [BidderStatus.RequestSent]: 'requestSent',\n [BidderStatus.QuoteReceived]: 'quoteReceived',\n [BidderStatus.DeclinedToQuote]: 'declinedToQuote',\n [BidderStatus.QuoteIsLate]: 'quoteIsLate',\n};\n\nconst BidderStatusDropdown: React.FC = (props) => {\n const { t } = useTranslation();\n\n const options = [\n {\n value: BidderStatus.RequestCreated,\n label: t('bid-package:bidderStatusRequestCreated'),\n },\n {\n value: BidderStatus.RequestSent,\n label: t('bid-package:bidderStatusRequestSent'),\n },\n {\n value: BidderStatus.QuoteReceived,\n label: t('bid-package:bidderStatusQuoteReceived'),\n },\n ];\n\n if (!props.isSelectedBidder) {\n options.push(\n {\n value: BidderStatus.DeclinedToQuote,\n label: t('bid-package:bidderStatusDeclinedToQuote'),\n },\n {\n value: BidderStatus.QuoteIsLate,\n label: t('bid-package:bidderStatusQuoteIsLate'),\n },\n );\n }\n\n return (\n
    \n \n {props.isReadOnly ? (\n
    \n \n \n \n \n {options.find((o) => o.value === props.bidder.status)?.label}\n \n
    \n ) : (\n
    \n props.onChange(props.bidder, Number(e.target.value) as BidderStatus)}\n data-testid=\"bidderStatusDropdown\"\n >\n {options.map((opt) => {\n return (\n \n );\n })}\n \n
    \n )}\n
    \n \n );\n};\n\nexport default BidderStatusDropdown;\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Bidder } from '../../../../../classes/odata/bidder';\nimport './BidderTrophyIcon.scss';\n\ninterface Props {\n selectedBidderId: string | undefined;\n bidder: Bidder;\n}\n\nconst BidderTrophyIcon: React.FC = (props) => {\n const { t } = useTranslation();\n\n const classNames = ['iconContainer', 'trophyIcon'];\n let iconText = '';\n let tooltip = '';\n\n const isSelectedBidder = props.selectedBidderId === props.bidder.id;\n const isSecondBidder = !!props.selectedBidderId && props.bidder.isSecondBidder();\n\n if (isSelectedBidder) {\n classNames.push('selectedBidder');\n iconText = t('bid-package:1st');\n tooltip = t('bid-package:trophyTooltipSelectedBidder');\n } else if (isSecondBidder) {\n classNames.push('secondBidder');\n iconText = t('bid-package:2nd');\n tooltip = t('bid-package:trophyTooltipSecondBidder');\n }\n\n return !(isSelectedBidder || isSecondBidder) ? (\n <>\n ) : (\n
    \n
    \n \n
    \n
    \n {iconText}\n
    \n
    \n );\n};\n\nexport default BidderTrophyIcon;\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport { sortBy } from 'lodash';\r\nimport React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Dropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reactstrap';\r\nimport { Subscription } from 'rxjs';\r\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\r\nimport { BidPackageLineItemRollupBid } from '../../../../../classes/odata/bid-package-line-item-rollup-bid';\r\nimport { Bidder, BidderStatus } from '../../../../../classes/odata/bidder';\r\nimport BidPackageConstants from '../../../../../constants/bid-package';\r\nimport { formatNumberAsCurrencyFull } from '../../../../../utils/general';\r\nimport BTIconButtonToggle from '../../../../common-page-components/controls/icon-button-toggle/BTIconButtonToggle';\r\nimport { BTPopoverContext } from '../../../../common-page-components/popover/BTPopoverContext';\r\nimport { BidderGridRowSortableContainerId } from '../BidPackagePage';\r\nimport useBidPackagePageContext from '../BidPackagePageContext';\r\nimport BidderStatusDropdown from '../components/BidderStatusDropdown';\r\nimport BidderTrophyIcon from '../components/BidderTrophyIcon';\r\nimport useBidderHelpers from './helpers/useBidderHelpers';\r\n\r\ninterface GenerateBidPackage_LineItems_Header_GridSection_Params {\r\n bidders: Bidder[];\r\n onBidderStatusChange: (bidder: Bidder, status: BidderStatus) => Promise;\r\n selectedBidderId: string | undefined;\r\n lineItemRollupBids: BidPackageLineItemRollupBid[];\r\n isReadOnly: boolean;\r\n lineItemsCountForSection: number;\r\n allLineItemsCount: number;\r\n}\r\n\r\ninterface ReturnValue {\r\n generateBidPackage_LineItems_Header_GridSection: (\r\n data: GenerateBidPackage_LineItems_Header_GridSection_Params,\r\n ) => BTGridSection | null;\r\n}\r\n\r\nconst useBidPackageGrid_LineItems_Header = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const {\r\n bidder_Select,\r\n lineItemRollupBid_Blur,\r\n lineItemRollupBid_Change,\r\n lineItems_Add,\r\n } = useBidPackagePageContext();\r\n\r\n const { getInputElementForBidField } = useBidderHelpers();\r\n\r\n const generateSubGrid_LineItemsHeader = useCallback(\r\n (\r\n gridSectionTestId: string,\r\n isReadOnly: boolean,\r\n lineItemsCountForSection: number,\r\n allLineItemsCount: number,\r\n ): BTSubGrid => {\r\n const lineItemHeaderRows: BTGridRowPrimary[] = [\r\n {\r\n id: '3b5eef8a-8406-4d01-a0ca-cb08e0fce650',\r\n isPrimaryGridRow: true,\r\n groupingLevel: null,\r\n isCollapsibleTrigger: false,\r\n collapseDirection: null,\r\n isHoverable: false,\r\n isSelectable: false,\r\n showBottomBorder: false,\r\n cells: [\r\n {\r\n cellContent: (\r\n
    \r\n \r\n {t('bid-package:lineItems')}\r\n\r\n {isReadOnly ? (\r\n <>\r\n ) : (\r\n ) => {\r\n // Canceling the event from triggering the collapse\r\n e.preventDefault();\r\n e.stopPropagation();\r\n lineItems_Add(null);\r\n }}\r\n value={false}\r\n disabled={isReadOnly}\r\n data-testid=\"addLineItemsButton\"\r\n />\r\n )}\r\n \r\n\r\n
    \r\n {allLineItemsCount >=\r\n BidPackageConstants.BID_PACKAGE_LINEITEMS_PERFORMANCE_THRESHOLD ? (\r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {lineItemsCountForSection > 0 ? (\r\n \r\n {lineItemsCountForSection}\r\n
    \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n \r\n ),\r\n cellWidth: 'fill',\r\n cellVerticalAlignment: 'bottom',\r\n cellAdditionalStyles: [\r\n 'border-sides',\r\n 'border-top',\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n 'padding-bottom-none',\r\n ],\r\n },\r\n ],\r\n },\r\n ];\r\n\r\n const lineItemColumnHeaderRow: BTGridRowPrimary = {\r\n id: 'd78cd184-0c92-4916-9301-dcce07c73047',\r\n isPrimaryGridRow: true,\r\n groupingLevel: null,\r\n isCollapsibleTrigger: false,\r\n collapseDirection: null,\r\n isHoverable: false,\r\n isSelectable: false,\r\n // Add cell to align with the drag handles and fix borders if LineItemOrdering is enabled\r\n cells: [\r\n // This cell is used to align with drag handles\r\n {\r\n cellWidth: isReadOnly ? 'none' : 'xs',\r\n cellContent:
    ,\r\n cellVerticalAlignment: 'bottom',\r\n cellAdditionalStyles: ['border-left'],\r\n },\r\n // This cell is to contain the drop down menu icon for the selected line items\r\n {\r\n cellWidth: isReadOnly ? 'none' : 'xs',\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellVerticalAlignment: 'bottom',\r\n },\r\n {\r\n cellWidth: 'xl',\r\n cellVerticalAlignment: 'bottom',\r\n cellContent:\r\n lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n },\r\n {\r\n cellWidth: 'sm',\r\n cellContent:\r\n lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n cellVerticalAlignment: 'bottom',\r\n cellHorizontalAlignment: 'right',\r\n },\r\n {\r\n cellWidth: 'sm',\r\n cellContent:\r\n lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n cellVerticalAlignment: 'bottom',\r\n cellHorizontalAlignment: 'left',\r\n },\r\n {\r\n cellWidth: 'sm',\r\n cellContent:\r\n lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n cellVerticalAlignment: 'bottom',\r\n cellHorizontalAlignment: 'right',\r\n },\r\n {\r\n cellWidth: 'fill',\r\n cellContent:\r\n lineItemsCountForSection > 0 ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n ),\r\n cellVerticalAlignment: 'bottom',\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-right'],\r\n },\r\n ],\r\n };\r\n\r\n lineItemHeaderRows.push(lineItemColumnHeaderRow);\r\n\r\n return {\r\n id: 'c66dd2e8-0a1c-4573-a497-5a0e6354a8a0',\r\n testId: `${gridSectionTestId}_PrimarySubGrid`,\r\n auxiliaryRows: lineItemHeaderRows,\r\n rows: [],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [lineItems_Add, t],\r\n );\r\n\r\n const generateSubGrids_Bidders = useCallback(\r\n (\r\n gridSectionTestId: string,\r\n bidders: Bidder[],\r\n onBidderStatusChange: (bidder: Bidder, status: BidderStatus) => Promise,\r\n selectedBidderId: string | undefined,\r\n lineItemRollupBids: BidPackageLineItemRollupBid[],\r\n isReadOnly: boolean,\r\n ): BTSubGrid[] => {\r\n const returnValue: BTSubGrid[] = [];\r\n\r\n sortBy(bidders, (b) => b.order).forEach((currBidder) => {\r\n const isSelectedBidder = currBidder.id === selectedBidderId;\r\n\r\n const rollupBidValue =\r\n BidPackage.getLineItemRollupBids(lineItemRollupBids, null).find(\r\n (v) => v.bidderId === currBidder.id && !v.metadataValue1 && !v.metadataValue2,\r\n )?.bidValue || null;\r\n\r\n const invalidStatusesForSelectedBidder = [\r\n BidderStatus.DeclinedToQuote,\r\n BidderStatus.QuoteIsLate,\r\n ];\r\n\r\n const bidderHasInvalidStatusForSelectedBidderOrReordering =\r\n currBidder.status && invalidStatusesForSelectedBidder.includes(currBidder.status);\r\n\r\n const preventBidderSelection =\r\n isReadOnly || bidderHasInvalidStatusForSelectedBidderOrReordering;\r\n\r\n // Bidder selection tooltip\r\n let bidderSelectTooltip;\r\n if (isReadOnly) {\r\n bidderSelectTooltip = '';\r\n } else if (isSelectedBidder) {\r\n bidderSelectTooltip = t('bid-package:clickToDeselectBidder');\r\n } else if (bidderHasInvalidStatusForSelectedBidderOrReordering) {\r\n bidderSelectTooltip = t('bid-package:bidderStatusSelectedBidderTooltip');\r\n } else {\r\n bidderSelectTooltip = t('bid-package:clickToSelectBidder');\r\n }\r\n\r\n const auxiliaryRows: BTGridRowBase[] = [\r\n {\r\n id: `${currBidder.id} - 890add41-3ed7-455b-a0be-54bc89cf31da`,\r\n isPrimaryGridRow: false,\r\n showBottomBorder: false,\r\n sortableInfo:\r\n selectedBidderId !== currBidder.id &&\r\n !bidderHasInvalidStatusForSelectedBidderOrReordering &&\r\n !isReadOnly\r\n ? {\r\n sortableContainerId: BidderGridRowSortableContainerId,\r\n sortableDirection: 'horizontal',\r\n }\r\n : undefined,\r\n metadata: {\r\n bidderName: currBidder.companyName!,\r\n },\r\n cells: [\r\n {\r\n cellContent: (\r\n
    \r\n
    \r\n {\r\n if (!preventBidderSelection) {\r\n bidder_Select(!isSelectedBidder ? currBidder.id || '' : null);\r\n }\r\n }}\r\n >\r\n {isSelectedBidder ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n \r\n )}\r\n \r\n {currBidder.companyName}\r\n \r\n
    \r\n\r\n \r\n
    \r\n\r\n
    \r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n {currBidder.primaryContactName}\r\n \r\n
    \r\n\r\n
    \r\n \r\n \r\n \r\n \r\n {currBidder.phoneNumber}\r\n \r\n
    \r\n\r\n
    \r\n \r\n \r\n \r\n \r\n {currBidder.primaryContactEmail}\r\n \r\n
    \r\n\r\n \r\n \r\n ),\r\n cellContentAdditionalClassNames: ['h-100'],\r\n cellWidth: 'md',\r\n cellBackgroundColor: isSelectedBidder ? 'blue' : 'none',\r\n cellAdditionalStyles: [\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n 'border-sides',\r\n 'border-top',\r\n ],\r\n frozenOnVerticalScroll: {\r\n // Use the bottom of the page header as the anchor element\r\n anchorElementSelector: '.gridPageHeader',\r\n },\r\n },\r\n ],\r\n },\r\n\r\n {\r\n id: `${currBidder.id} - 240243fc-9781-4fc3-9bb2-48d1cb6b3756`,\r\n isPrimaryGridRow: false,\r\n cells: [\r\n {\r\n cellTriggersBTPopover: (rollupBidValue ?? 0) > 0,\r\n onCellMouseEnter: (e) => {\r\n if (rollupBidValue) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(rollupBidValue || 0),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n },\r\n onCellMouseLeave: () => {\r\n if (rollupBidValue) {\r\n setDisplayedPopoverInfo(null);\r\n }\r\n },\r\n cellWidth: 'md',\r\n cellBackgroundColor: isSelectedBidder ? 'blue' : 'none',\r\n cellAdditionalStyles: ['border-sides'],\r\n dataAttributes: {\r\n 'alternate-name': '',\r\n 'line-item-description': '',\r\n 'line-item-metadata1': '',\r\n 'line-item-metadata2': '',\r\n 'bidder-name': currBidder.companyName || '',\r\n },\r\n cellContent: (\r\n <>\r\n {getInputElementForBidField({\r\n inputType: 'number',\r\n isLineItem: false,\r\n price: rollupBidValue,\r\n value: undefined,\r\n classification: undefined,\r\n placeholder: undefined,\r\n isDisabled: isReadOnly,\r\n onBidChangeCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n lineItemRollupBid_Change({\r\n bidderId: currBidder.id || '',\r\n alternateId: undefined,\r\n lineItemRollup1: null,\r\n lineItemRollup2: null,\r\n price: bidderValue.price,\r\n classification: undefined,\r\n value: undefined,\r\n });\r\n },\r\n\r\n onBidBlurCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n lineItemRollupBid_Blur({\r\n bidderId: currBidder.id || '',\r\n alternateId: undefined,\r\n lineItemRollup1: null,\r\n lineItemRollup2: null,\r\n price: bidderValue.price,\r\n classification: undefined,\r\n value: undefined,\r\n });\r\n },\r\n })}\r\n \r\n ),\r\n },\r\n ],\r\n },\r\n ];\r\n\r\n const testId = `${gridSectionTestId}_SubGrid_${currBidder!.companyName!.replace(\r\n / /g,\r\n '_',\r\n )}`;\r\n\r\n returnValue.push({\r\n id: `Bidder SubGrid - Line Items - ${testId}`,\r\n testId: testId,\r\n auxiliaryRows: auxiliaryRows,\r\n rows: [],\r\n addLeftPadding: true,\r\n });\r\n });\r\n\r\n return returnValue;\r\n },\r\n [\r\n t,\r\n getInputElementForBidField,\r\n bidder_Select,\r\n setDisplayedPopoverInfo,\r\n lineItemRollupBid_Change,\r\n lineItemRollupBid_Blur,\r\n ],\r\n );\r\n\r\n const generateBidPackage_LineItems_Header_GridSection = useCallback(\r\n (data: GenerateBidPackage_LineItems_Header_GridSection_Params): BTGridSection | null => {\r\n const gridSectionTestId = 'BidPackagePage_GridSection_LineItems_Header';\r\n\r\n const lineItemsSubGrid = generateSubGrid_LineItemsHeader(\r\n gridSectionTestId,\r\n data.isReadOnly,\r\n data.lineItemsCountForSection,\r\n data.allLineItemsCount,\r\n );\r\n\r\n const biddersSubGrids = generateSubGrids_Bidders(\r\n gridSectionTestId,\r\n data.bidders,\r\n data.onBidderStatusChange,\r\n data.selectedBidderId,\r\n data.lineItemRollupBids,\r\n data.isReadOnly,\r\n );\r\n\r\n return {\r\n id: BidPackageConstants.GridSectionIds.LINE_ITEMS_HEADER,\r\n primaryGrid: lineItemsSubGrid!,\r\n secondaryGrids: biddersSubGrids,\r\n testId: gridSectionTestId,\r\n };\r\n },\r\n [generateSubGrid_LineItemsHeader, generateSubGrids_Bidders],\r\n );\r\n\r\n return {\r\n generateBidPackage_LineItems_Header_GridSection,\r\n };\r\n};\r\n\r\n// NOTE: This is its own component instead of all in the hook so when the observables fire and state updates,\r\n// it doesn't cause re-renders of the calling component and it self-contained.\r\nconst LineItemsDropDownMenu: React.FC = () => {\r\n const { t } = useTranslation();\r\n\r\n const {\r\n selectedLineItemsMappings$,\r\n lineItems_Delete,\r\n lineItems_Edit,\r\n } = useBidPackagePageContext();\r\n\r\n const [dropdownMenuIconIsDisplayed, setDropdownMenuIconIsDisplayed] = useState(false);\r\n\r\n const [lineItemsActionDropdownIsOpen, setLineItemsActionDropdownIsOpen] = useState(\r\n false,\r\n );\r\n\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n selectedLineItemsMappings$.subscribe((lineItemMappings) => {\r\n setDropdownMenuIconIsDisplayed((lineItemMappings['']?.length || 0) > 0);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [selectedLineItemsMappings$]);\r\n\r\n const onDropdownToggle = useCallback(() => {\r\n setLineItemsActionDropdownIsOpen((v) => !v);\r\n }, []);\r\n\r\n return (\r\n <>\r\n {dropdownMenuIconIsDisplayed ? (\r\n \r\n \r\n \r\n \r\n\r\n \r\n lineItems_Edit(null)}>\r\n \r\n {t('general:edit')}\r\n \r\n lineItems_Delete(null)}>\r\n \r\n {t('general:delete')}\r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n \r\n );\r\n};\r\n\r\n// NOTE: This is its own component instead of all in the hook so when the observables fire and state updates,\r\n// it doesn't cause re-renders of the calling component and it self-contained.\r\ninterface BiddersDropDownMenuProps {\r\n bidder: Bidder;\r\n isReadOnly: boolean;\r\n}\r\n\r\nconst BiddersDropDownMenu: React.FC = ({ bidder, isReadOnly }) => {\r\n const { t } = useTranslation();\r\n\r\n const [bidderNameForOpenDropdown, setBidderNameForOpenDropdown] = useState<\r\n string | null | undefined\r\n >(null);\r\n\r\n const {\r\n bidder_Delete,\r\n bidder_Edit,\r\n bidder_EditDocuments,\r\n bidder_EditNotes,\r\n bidder_ShowInfo,\r\n } = useBidPackagePageContext();\r\n\r\n const companyName = bidder.companyName;\r\n\r\n const onDropdownToggle = useCallback(() => {\r\n if (bidderNameForOpenDropdown === companyName) {\r\n setBidderNameForOpenDropdown(null);\r\n } else {\r\n setBidderNameForOpenDropdown(companyName);\r\n }\r\n }, [bidderNameForOpenDropdown, companyName]);\r\n\r\n return useMemo(() => {\r\n return (\r\n <>\r\n \r\n \r\n {\r\n setBidderNameForOpenDropdown(companyName);\r\n }}\r\n value={false}\r\n data-testid=\"bidderEditDropdownToggleButton\"\r\n />\r\n \r\n\r\n \r\n bidder_ShowInfo(bidder)}>\r\n \r\n \r\n \r\n {t('general:info')}\r\n \r\n\r\n bidder_EditNotes(bidder)}>\r\n \r\n \r\n \r\n {t('general:notes')}\r\n \r\n\r\n bidder_EditDocuments(bidder)}>\r\n \r\n \r\n \r\n {t('bid-package:documents')}\r\n \r\n\r\n {isReadOnly ? (\r\n <>\r\n ) : (\r\n <>\r\n \r\n\r\n bidder_Edit(bidder)}>\r\n \r\n \r\n \r\n {t('general:edit')}\r\n \r\n\r\n bidder_Delete(bidder)}>\r\n \r\n \r\n \r\n {t('general:remove')}\r\n \r\n \r\n )}\r\n \r\n \r\n \r\n );\r\n }, [\r\n bidder,\r\n bidderNameForOpenDropdown,\r\n bidder_Delete,\r\n bidder_Edit,\r\n bidder_EditDocuments,\r\n bidder_EditNotes,\r\n bidder_ShowInfo,\r\n companyName,\r\n isReadOnly,\r\n onDropdownToggle,\r\n t,\r\n ]);\r\n};\r\n\r\nexport default useBidPackageGrid_LineItems_Header;\r\n","import React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\r\nimport { BidPackageRequirement } from '../../../../../classes/odata/bid-package-requirement';\r\nimport { Bidder } from '../../../../../classes/odata/bidder';\r\nimport { generateEmptyGridRowWithNoCells_Primary } from '../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n normalizeNullOrUndefined,\r\n} from '../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../common-page-components/popover/BTPopoverContext';\r\nimport {\r\n BidClassificationTypes,\r\n RequirementFulfillmentTypes,\r\n} from '../../../../enums/bid-package-enums';\r\nimport useBidPackagePageContext from '../BidPackagePageContext';\r\nimport { BidPackageRequirementFulfillment } from './../../../../../classes/odata/bid-package-requirement-fulfillment';\r\nimport useBidderHelpers from './helpers/useBidderHelpers';\r\n\r\ntype RequirementType = 'general' | 'trade';\r\n\r\ninterface ReturnValue {\r\n generateBidPackage_Requirements_GridSection: (\r\n bidders: Bidder[],\r\n requirements: BidPackageRequirement[],\r\n selectedBidderId: string | undefined,\r\n gridSectionId: string,\r\n requirementType: RequirementType,\r\n isReadOnly: boolean,\r\n ) => BTGridSection | null;\r\n}\r\n\r\nconst collapsibleIconJSXElementFactory = (element: JSX.Element): JSX.Element =>

    {element}

    ;\r\n\r\nconst useBidPackageGrid_Requirements = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n const {\r\n requirementFulfillment_Blur,\r\n requirementFulfillment_Change,\r\n requirementFulfillment_Focus,\r\n } = useBidPackagePageContext();\r\n\r\n const { getInputElementForBidField } = useBidderHelpers();\r\n\r\n const generateSubGrid_Requirements = useCallback(\r\n (\r\n gridSectionId: string,\r\n requirementType: RequirementType,\r\n requirements: BidPackageRequirement[],\r\n gridSectionTestId: string,\r\n ): BTSubGrid => {\r\n const requirementsCountForType = requirements.filter(\r\n (v) => v.requirementType?.toLowerCase() === requirementType.toLowerCase(),\r\n ).length;\r\n\r\n const auxiliaryRows: BTGridRowPrimary[] = [\r\n {\r\n ...generateEmptyGridRowWithNoCells_Primary(\r\n `${gridSectionId} - 67e2a854-efae-4b23-b568-331e2f2b8ab5`,\r\n ),\r\n showBottomBorder: false,\r\n cells: [\r\n {\r\n cellContent: (\r\n

    \r\n \r\n {requirementType} {t('general:requirements')} ({requirementsCountForType})\r\n \r\n

    \r\n ),\r\n cellWidth: 'fill',\r\n cellAdditionalStyles: ['border-sides'],\r\n },\r\n ],\r\n groupingLevel: null,\r\n groupingInfo: {\r\n isGroupedRow: false,\r\n order: null,\r\n groupingLevel: null,\r\n groupingKey1: `Requirement - ${requirementType}`,\r\n groupingKey2: null,\r\n globalCollapseResponseKey: null,\r\n globalCollapseTriggerKey: null,\r\n },\r\n },\r\n ];\r\n\r\n if (requirements.length > 0) {\r\n auxiliaryRows[0].isCollapsibleTrigger = true;\r\n auxiliaryRows[0].collapsibleIconJSXElementFactory = collapsibleIconJSXElementFactory;\r\n }\r\n\r\n const requirementRows: BTGridRowPrimary[] = [];\r\n\r\n requirements.forEach((currRequirement) => {\r\n const newRowObj: BTGridRowPrimary = {\r\n id: `${gridSectionId} - Requirement - ${currRequirement.description}`,\r\n isPrimaryGridRow: true,\r\n cells: [],\r\n groupingLevel: null,\r\n isCollapsibleTrigger: false,\r\n collapseDirection: null,\r\n isHoverable: true,\r\n isSelectable: false,\r\n groupingInfo: {\r\n isGroupedRow: false,\r\n order: null,\r\n groupingLevel: null,\r\n groupingKey1: `Requirement - ${requirementType}`,\r\n groupingKey2: null,\r\n globalCollapseResponseKey: null,\r\n globalCollapseTriggerKey: null,\r\n },\r\n };\r\n\r\n newRowObj.cells.push({\r\n cellWidth: 'fill',\r\n cellContent: (\r\n // NOTE: The nested divs are important here, for the cell content overflow CSS to work correctly\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n ),\r\n cellAdditionalStyles: ['border-sides'],\r\n frozenOnHorizontalScroll: true,\r\n trimTextOnOverflow: true,\r\n });\r\n\r\n requirementRows.push(newRowObj);\r\n });\r\n\r\n return {\r\n id: `${gridSectionId} - 38748fa7-f67f-480d-bab4-0073b37c3fbc`,\r\n testId: `${gridSectionTestId}_PrimarySubGrid`,\r\n auxiliaryRows: auxiliaryRows,\r\n rows: requirementRows,\r\n addLeftPadding: false,\r\n };\r\n },\r\n [t],\r\n );\r\n\r\n const generateSubGrids_Bidders = useCallback(\r\n (\r\n bidders: Bidder[],\r\n selectedBidderId: string | undefined,\r\n gridSectionId: string,\r\n requirementType: RequirementType,\r\n gridSectionTestId: string,\r\n requirements: BidPackageRequirement[],\r\n isReadOnly: boolean,\r\n ): BTSubGrid[] => {\r\n const returnValue: BTSubGrid[] = [];\r\n\r\n (bidders || []).forEach((currBidder) => {\r\n const isSelectedBidder = currBidder.id === selectedBidderId;\r\n\r\n const auxiliaryRows: BTGridRowBase[] = [];\r\n const bidderRows: BTGridRowBase[] = [];\r\n\r\n // Add an empty row\r\n auxiliaryRows.push({\r\n id: `${gridSectionId} - ${currBidder.id} - 74e4f3c3-cb85-4f42-a71d-d2df09744574`,\r\n cells: [\r\n {\r\n cellContent: (\r\n // NOTE: We need this test ID / class on this element for use with WalkMe\r\n \r\n  \r\n \r\n ),\r\n cellWidth: 'md',\r\n cellBackgroundColor: isSelectedBidder ? 'blue' : 'none',\r\n cellAdditionalStyles: ['border-sides'],\r\n },\r\n ],\r\n isPrimaryGridRow: false,\r\n showBottomBorder: false,\r\n });\r\n\r\n requirements.forEach((currRequirement) => {\r\n const bidderRequirementRow: BTGridRowBase = {\r\n id: `${gridSectionId} - ${currRequirement.id} - 3c435a9b-06cf-41a4-ac5e-a77855b59406`,\r\n cells: [\r\n {\r\n cellContent:
    ,\r\n cellWidth: 'md',\r\n cellBackgroundColor: isSelectedBidder ? 'blue' : 'none',\r\n cellAdditionalStyles: ['border-sides'],\r\n },\r\n ],\r\n isPrimaryGridRow: false,\r\n isHoverable: true,\r\n };\r\n\r\n const matchingFulfillmentObj = currRequirement.requirementFulfillments.find(\r\n (v) => v.bidderId === currBidder.id,\r\n );\r\n\r\n switch (currRequirement.requirementFulfillmentType) {\r\n case RequirementFulfillmentTypes.Quantitative:\r\n {\r\n const price =\r\n matchingFulfillmentObj?.price !== undefined\r\n ? matchingFulfillmentObj?.price\r\n : undefined;\r\n\r\n const classification =\r\n matchingFulfillmentObj?.classification || BidClassificationTypes.Unallocated;\r\n\r\n let requirementFulfillment_PlaceholderValue: string | null = null;\r\n\r\n const matchingBid:\r\n | BidPackageRequirementFulfillment\r\n | undefined = currRequirement.requirementFulfillments.find(\r\n (v) => v.bidderId === currBidder.id,\r\n );\r\n const matchingRequirement = requirements.find((v) => v.id === currRequirement.id);\r\n\r\n // Set a placeholder value for \"missing scope\" bids without a value defined\r\n if (matchingRequirement && matchingBid) {\r\n if (\r\n matchingBid.classification === BidClassificationTypes.MissingScope &&\r\n normalizeNullOrUndefined(matchingBid.price) === null\r\n ) {\r\n requirementFulfillment_PlaceholderValue = formatNumberAsCurrency(\r\n BidPackage.calculateRequirementFulfillmentBidValue(\r\n matchingRequirement,\r\n currBidder.id!,\r\n ),\r\n );\r\n }\r\n }\r\n\r\n const requirementCell = bidderRequirementRow.cells[0];\r\n const requirementHasPriceOrPlaceholderValue =\r\n typeof price === 'number' || requirementFulfillment_PlaceholderValue;\r\n\r\n requirementCell.cellTriggersBTPopover = requirementHasPriceOrPlaceholderValue\r\n ? true\r\n : false;\r\n\r\n requirementCell.onCellMouseEnter = (e) => {\r\n if (requirementHasPriceOrPlaceholderValue) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: requirementFulfillment_PlaceholderValue\r\n ? requirementFulfillment_PlaceholderValue\r\n : formatNumberAsCurrencyFull(price || 0),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n };\r\n requirementCell.onCellMouseLeave = () => {\r\n if (requirementHasPriceOrPlaceholderValue) {\r\n setDisplayedPopoverInfo(null);\r\n }\r\n };\r\n requirementCell.cellContent = getInputElementForBidField({\r\n inputType: 'combo',\r\n isLineItem: false,\r\n price,\r\n value: undefined,\r\n classification,\r\n isDisabled: isReadOnly,\r\n placeholder: requirementFulfillment_PlaceholderValue || '',\r\n onBidFocusCallback: () => {\r\n requirementFulfillment_Focus({\r\n bidderId: currBidder.id!,\r\n requirementId: currRequirement.id!,\r\n });\r\n },\r\n onBidChangeCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n requirementFulfillment_Change({\r\n ...bidderValue,\r\n bidderId: currBidder.id,\r\n requirementId: currRequirement.id,\r\n });\r\n },\r\n onBidBlurCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n requirementFulfillment_Blur({\r\n ...bidderValue,\r\n bidderId: currBidder.id,\r\n requirementId: currRequirement.id,\r\n });\r\n },\r\n });\r\n }\r\n break;\r\n\r\n case RequirementFulfillmentTypes.Qualitative:\r\n {\r\n // NOTE: The existence of the fulfillment object is all we need for a qualitative fulfillment\r\n const value = matchingFulfillmentObj !== undefined;\r\n\r\n bidderRequirementRow.cells[0].cellContent = getInputElementForBidField({\r\n inputType: 'checkbox',\r\n isLineItem: false,\r\n price: undefined,\r\n value,\r\n classification: undefined,\r\n placeholder: undefined,\r\n isDisabled: isReadOnly,\r\n onBidFocusCallback: () => {\r\n requirementFulfillment_Focus({\r\n bidderId: currBidder.id!,\r\n requirementId: currRequirement.id!,\r\n });\r\n },\r\n onBidChangeCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n requirementFulfillment_Change({\r\n ...bidderValue,\r\n bidderId: currBidder.id,\r\n requirementId: currRequirement.id,\r\n });\r\n },\r\n onBidBlurCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n requirementFulfillment_Blur({\r\n ...bidderValue,\r\n bidderId: currBidder.id,\r\n requirementId: currRequirement.id,\r\n });\r\n },\r\n });\r\n }\r\n break;\r\n\r\n case RequirementFulfillmentTypes.Freeform:\r\n {\r\n const value1 = matchingFulfillmentObj?.value || '';\r\n bidderRequirementRow.cells[0].cellContent = getInputElementForBidField({\r\n inputType: 'text',\r\n isLineItem: false,\r\n price: undefined,\r\n value: value1,\r\n classification: undefined,\r\n placeholder: undefined,\r\n isDisabled: isReadOnly,\r\n onBidFocusCallback: () => {\r\n requirementFulfillment_Focus({\r\n bidderId: currBidder.id!,\r\n requirementId: currRequirement.id!,\r\n });\r\n },\r\n onBidChangeCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n requirementFulfillment_Change({\r\n ...bidderValue,\r\n bidderId: currBidder.id,\r\n requirementId: currRequirement.id,\r\n });\r\n },\r\n onBidBlurCallback: (bidderValue: BidderValue) => {\r\n // Add some extra info to the event, then bubble it up\r\n requirementFulfillment_Blur({\r\n ...bidderValue,\r\n bidderId: currBidder.id,\r\n requirementId: currRequirement.id,\r\n });\r\n },\r\n });\r\n }\r\n break;\r\n\r\n default:\r\n // console.log(\r\n // `Invalid requirement fulfillment type: '${currRequirement.requirementFulfillmentType}'`,\r\n // );\r\n break;\r\n }\r\n\r\n bidderRows.push(bidderRequirementRow);\r\n });\r\n\r\n const testId = `${gridSectionTestId}_SubGrid_${currBidder!.companyName!.replace(\r\n / /g,\r\n '_',\r\n )}`;\r\n\r\n returnValue.push({\r\n id: `${gridSectionId} - ${testId}`,\r\n testId: testId,\r\n auxiliaryRows: auxiliaryRows,\r\n rows: bidderRows,\r\n addLeftPadding: true,\r\n });\r\n });\r\n\r\n return returnValue;\r\n },\r\n [\r\n getInputElementForBidField,\r\n requirementFulfillment_Blur,\r\n requirementFulfillment_Change,\r\n requirementFulfillment_Focus,\r\n setDisplayedPopoverInfo,\r\n ],\r\n );\r\n\r\n const generateBidPackage_Requirements_GridSection = useCallback(\r\n (\r\n bidders: Bidder[],\r\n requirements: BidPackageRequirement[],\r\n selectedBidderId: string | undefined,\r\n gridSectionId: string,\r\n requirementType: RequirementType,\r\n isReadOnly: boolean,\r\n ): BTGridSection | null => {\r\n if (!requirements.length) {\r\n return null;\r\n }\r\n\r\n const gridSectionTestId = `BidPackagePage_GridSection_${\r\n requirementType === 'general' ? 'General' : 'Trade'\r\n }_Requirements`;\r\n\r\n const requirementsToDisplay =\r\n requirementType === 'general'\r\n ? BidPackage.getGeneralRequirements(requirements)\r\n : BidPackage.getTradeRequirements(requirements);\r\n\r\n const requirementsSubGrid = generateSubGrid_Requirements(\r\n gridSectionId,\r\n requirementType,\r\n requirementsToDisplay,\r\n gridSectionTestId,\r\n );\r\n const biddersSubGrids = generateSubGrids_Bidders(\r\n bidders,\r\n selectedBidderId,\r\n gridSectionId,\r\n requirementType,\r\n gridSectionTestId,\r\n requirementsToDisplay,\r\n isReadOnly,\r\n );\r\n\r\n return {\r\n id: gridSectionId,\r\n testId: gridSectionTestId,\r\n primaryGrid: requirementsSubGrid,\r\n secondaryGrids: biddersSubGrids,\r\n };\r\n },\r\n [generateSubGrid_Requirements, generateSubGrids_Bidders],\r\n );\r\n\r\n return {\r\n generateBidPackage_Requirements_GridSection,\r\n };\r\n};\r\n\r\nexport default useBidPackageGrid_Requirements;\r\n","import { useCallback } from 'react';\nimport { Adjustment } from '../../../../../classes/odata/adjustment';\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\nimport { BidPackageLineItem } from '../../../../../classes/odata/bid-package-line-item';\nimport { BidPackageLineItemBid } from '../../../../../classes/odata/bid-package-line-item-bid';\nimport { BidPackageLineItemGroupOrder } from '../../../../../classes/odata/bid-package-line-item-group-order';\nimport { BidPackageLineItemMetadata } from '../../../../../classes/odata/bid-package-line-item-metadata';\nimport { BidPackageLineItemOrder } from '../../../../../classes/odata/bid-package-line-item-order';\nimport { BidPackageLineItemRollupBid } from '../../../../../classes/odata/bid-package-line-item-rollup-bid';\nimport { BidPackageRequirement } from '../../../../../classes/odata/bid-package-requirement';\nimport { BidPackageRequirementFulfillment } from '../../../../../classes/odata/bid-package-requirement-fulfillment';\nimport { Bidder } from '../../../../../classes/odata/bidder';\nimport { useLogger } from '../../../../../services/logger/Logger';\nimport { nameof } from '../../../../../utils/nameof';\n\ninterface ReturnValue {\n executeBidPackageChangeHandler: (\n bidPackage: BidPackage,\n type: 'add' | 'update' | 'delete',\n entry: DataChangedEntry,\n ) => BidPackage | null;\n}\n\nconst useBidPackage_ChangeNotifications = (): ReturnValue => {\n const logger = useLogger();\n\n //\n // Executes the change handler of the provided type against the bid package and updates state\n //\n const executeBidPackageChangeHandler = useCallback(\n (\n bidPackage: BidPackage,\n type: 'add' | 'update' | 'delete',\n entry: DataChangedEntry,\n ): BidPackage | null => {\n const dataEntryType = entry.Type as DataChangedEntryTypes_BidPackagePage_BidPackage;\n const handler = DataChangeHandlerMap[dataEntryType];\n\n if (!handler) {\n return null;\n }\n\n // Invoke the handle function for the given type\n try {\n let updatedBidPackage: BidPackage | null = null;\n switch (type) {\n case 'add':\n updatedBidPackage = handler.onAdd(bidPackage, entry);\n break;\n case 'update':\n updatedBidPackage = handler.onUpdate(bidPackage, entry);\n break;\n case 'delete':\n updatedBidPackage = handler.onDelete(bidPackage, entry);\n break;\n default:\n throw new Error(`executeChangeHandler: unsupported type ${type}`);\n }\n\n // If the bid package was not updated, there's nothing to change\n if (!updatedBidPackage) {\n return null;\n }\n\n // NOTE: Bidder changes could affect ordering so we must sort the collection here again\n if (dataEntryType === 'Bidder') {\n updatedBidPackage.sortBidders();\n }\n\n // Return the updated bid package\n return updatedBidPackage;\n } catch (error) {\n // If an error occurs in a change handler, log it and return null\n logger.logError(error);\n return null;\n }\n },\n [logger],\n );\n\n return {\n executeBidPackageChangeHandler,\n };\n};\n\nconst addArrayItemToBidPackage = (\n bidPackage: BidPackage,\n entry: DataChangedEntry,\n arrayPropName: keyof BidPackage,\n oDataClass: Ctor,\n): BidPackage => {\n const array = bidPackage[arrayPropName] as unknown[];\n const arrayClone = [...array];\n\n // Add new entity\n arrayClone.push(new oDataClass({ ...entry.Values }));\n\n // Replace array with clone\n // NOTE: We have to cast to any to set the prop\n const castedBidPackage = bidPackage as any; // eslint-disable-line @typescript-eslint/no-explicit-any\n castedBidPackage[arrayPropName] = arrayClone;\n\n return castedBidPackage as BidPackage;\n};\n\nconst updateArrayItemInBidPackage = (\n bidPackage: BidPackage,\n entry: DataChangedEntry,\n arrayPropName: keyof BidPackage,\n oDataClass: Ctor,\n): BidPackage | null => {\n const array = bidPackage[arrayPropName] as { id: string | undefined }[];\n const arrayClone = [...array];\n\n // Get index of entity by ID\n const entityId = entry.Values['id'] as string;\n const index = arrayClone.findIndex((entity) => entity.id === entityId);\n if (index === -1) {\n return null;\n }\n\n const updatedEntity = new oDataClass({\n ...arrayClone[index], // Start with current entity values\n ...entry.Values, // Override with values provided in message\n });\n\n // Update in array\n arrayClone[index] = updatedEntity;\n\n // Replace array with clone\n // NOTE: We have to cast to any to set the prop\n const castedBidPackage = bidPackage as any; // eslint-disable-line @typescript-eslint/no-explicit-any\n castedBidPackage[arrayPropName] = arrayClone;\n\n return castedBidPackage as BidPackage;\n};\n\nconst removeArrayItemFromBidPackage = (\n bidPackage: BidPackage,\n entry: DataChangedEntry,\n arrayPropName: keyof BidPackage,\n): BidPackage | null => {\n const array = bidPackage[arrayPropName] as { id: string | undefined }[];\n const arrayClone = [...array];\n\n // Get index of entity by ID\n const entityId = entry.Values['id'] as string;\n const index = arrayClone.findIndex((entity) => entity.id === entityId);\n if (index === -1) {\n return null;\n }\n\n // Remove entity from array\n arrayClone.splice(index, 1);\n\n // Replace array with clone\n // NOTE: We have to cast to any to set the prop\n const castedBidPackage = bidPackage as any; // eslint-disable-line @typescript-eslint/no-explicit-any\n castedBidPackage[arrayPropName] = arrayClone;\n\n return castedBidPackage as BidPackage;\n};\n\ninterface DataChangeHandler {\n onAdd: (entity: T, entry: DataChangedEntry) => T | null;\n onUpdate: (entity: T, entry: DataChangedEntry) => T | null;\n onDelete: (entity: T, entry: DataChangedEntry) => T | null;\n}\n\n//\n// A map from oDataResourceName to DataChangeHandler\n//\nconst DataChangeHandlerMap: Record<\n DataChangedEntryTypes_BidPackagePage_BidPackage,\n DataChangeHandler\n> = {\n BidPackage: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We shouldn't get a change notification for an added bid package since\n // changes are scoped to a specific bid package\n return null;\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('id')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n return new BidPackage({\n ...bidPackage,\n ...entry.Values,\n });\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: The deleted bid package is handled via the onChangeHandlerCompleteCallback\n return null;\n },\n },\n BidPackageLineItem: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n return addArrayItemToBidPackage(bidPackage, entry, 'lineItems', BidPackageLineItem);\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n return updateArrayItemInBidPackage(bidPackage, entry, 'lineItems', BidPackageLineItem);\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n return removeArrayItemFromBidPackage(bidPackage, entry, 'lineItems');\n },\n },\n BidPackageLineItemOrder: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const lineItemId = entry.Values['bidPackageLineItemId'] as string;\n if (!lineItemId) {\n return null;\n }\n const lineItemToUpdate = bidPackage.getLineItemById(lineItemId);\n if (!lineItemToUpdate) {\n return null;\n }\n lineItemToUpdate.mappedOrder = new BidPackageLineItemOrder({ ...entry.Values });\n return bidPackage;\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const lineItemId = entry.Values['bidPackageLineItemId'] as string;\n if (!lineItemId) {\n return null;\n }\n const lineItemToUpdate = bidPackage.getLineItemById(lineItemId);\n if (!lineItemToUpdate) {\n return null;\n }\n lineItemToUpdate.mappedOrder = new BidPackageLineItemOrder({\n ...lineItemToUpdate.mappedOrder,\n ...entry.Values,\n });\n return bidPackage;\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not delete order\n return null;\n },\n },\n BidPackageLineItemGroupOrder: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry =\n entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n return addArrayItemToBidPackage(\n bidPackage,\n entry,\n 'lineItemGroupOrders',\n BidPackageLineItemGroupOrder,\n );\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry =\n entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n return updateArrayItemInBidPackage(\n bidPackage,\n entry,\n 'lineItemGroupOrders',\n BidPackageLineItemGroupOrder,\n );\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n return removeArrayItemFromBidPackage(bidPackage, entry, 'lineItemGroupOrders');\n },\n },\n BidPackageLineItemMetadata: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const lineItemId = entry.Values['bidPackageLineItemId'] as string;\n if (!lineItemId) {\n return null;\n }\n const lineItemToUpdate = bidPackage.getLineItemById(lineItemId);\n if (!lineItemToUpdate) {\n return null;\n }\n lineItemToUpdate.setMetadata(new BidPackageLineItemMetadata({ ...entry.Values }));\n return bidPackage;\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n return null; // metadata isn't update; it's added/deleted only\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const lineItemId = entry.Values['bidPackageLineItemId'] as string;\n if (!lineItemId) {\n return null;\n }\n const metadataId = entry.Values['id'] as string;\n if (!metadataId) {\n return null;\n }\n const lineItemToUpdate = bidPackage.getLineItemById(lineItemId);\n if (!lineItemToUpdate) {\n return null;\n }\n lineItemToUpdate.removeMetadata(metadataId);\n\n return bidPackage;\n },\n },\n Bidder: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n return addArrayItemToBidPackage(bidPackage, entry, 'bidders', Bidder);\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n return updateArrayItemInBidPackage(bidPackage, entry, 'bidders', Bidder);\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n return removeArrayItemFromBidPackage(bidPackage, entry, 'bidders');\n },\n },\n BidderFileUpload: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: we don't do anything specific with the bidder file upload on the bid package page\n // so do nothing here.\n return null;\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: we don't do anything specific with the bidder file upload on the bid package page\n // so do nothing here.\n return null;\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: we don't do anything specific with the bidder file upload on the bid package page\n // so do nothing here.\n return null;\n },\n },\n BidPackageLineItemBid: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n // NOTE: We can't do just an add here because line item bids are preemptively added\n // in the onChangeHandler. Instead, we must use the setter on the BidPackage class\n // which does an upsert based on the key (bidPackageLineItemId)\n\n const lineItemId = entry.Values[\n nameof('bidPackageLineItemId')\n ] as string;\n\n if (!lineItemId) {\n throw new Error('BidPackageLineItemBid.onAdd: Could not get bidPackageLineItemId for bid');\n }\n\n const bid = new BidPackageLineItemBid({ ...entry.Values });\n bidPackage.setLineItemBid(lineItemId, bid, true);\n return bidPackage;\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We shouldn't get an update here, an edit is really a delete and an add\n return null;\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const lineItemId = entry.Values[\n nameof('bidPackageLineItemId')\n ] as string;\n\n if (!lineItemId) {\n throw new Error(\n 'BidPackageLineItemBid.onDelete: Could not get bidPackageLineItemId for bid',\n );\n }\n\n const bidderId = entry.Values[nameof('bidderId')] as string;\n if (!bidderId) {\n throw new Error('BidPackageLineItemBid.onDelete: Could not get bidderId for bid');\n }\n\n bidPackage.deleteLineItemBid(lineItemId, bidderId, true);\n\n return bidPackage;\n },\n },\n BidPackageLineItemRollupBid: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n // NOTE: We can't do just an add here because rollup bids are preemptively added\n // in the onChangeHandler. Instead, we must use the setter on the BidPackage class\n // which does an upsert based on the composite key (bidderId and alternateId)\n const rollupBid = new BidPackageLineItemRollupBid({ ...entry.Values });\n bidPackage.setLineItemRollupBid(rollupBid, true);\n return bidPackage;\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We shouldn't get an update here, an edit is really a delete and an add\n return null;\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const entityId = entry.Values['id'] as string;\n const rollupBid = bidPackage.lineItemRollupBids.find((v) => v.id === entityId);\n\n if (rollupBid) {\n bidPackage.deleteLineItemRollupBid(\n rollupBid.alternateId ?? null,\n rollupBid.bidderId!,\n rollupBid.metadataValue1 ?? null,\n rollupBid.metadataValue2 ?? null,\n true,\n );\n }\n\n return bidPackage;\n },\n },\n Adjustment: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n // NOTE: We can't do just an add here because adjustments are preemptively added\n // in the onChangeHandler. Instead, we must use the setter on the BidPackage class\n // which does an upsert based on the composite key (bidderId and alternateId)\n const adjustment = new Adjustment({ ...entry.Values });\n bidPackage.setAdjustment(adjustment, true, true);\n return bidPackage;\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n // NOTE: We will get an update here when the adjustment notes updates\n const adjustment = new Adjustment({ ...entry.Values });\n bidPackage.setAdjustment(adjustment, true, true);\n return bidPackage;\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const entityId = entry.Values['id'] as string;\n const adjustmentToDelete = bidPackage.adjustments.find((v) => v.id === entityId);\n\n if (adjustmentToDelete) {\n bidPackage.deleteAdjustment(\n adjustmentToDelete.alternateId ?? null,\n adjustmentToDelete.bidderId!,\n true,\n );\n }\n\n return bidPackage;\n },\n },\n BidPackageRequirement: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('bidPackageId')];\n if (bidPackage.id !== bidPackageIdOfEntry) {\n return bidPackage;\n }\n\n const requirementId = entry.Values[nameof('id')];\n\n if (!bidPackage.requirements.find((v) => v.id === requirementId)) {\n bidPackage.requirements.push(\n new BidPackageRequirement({\n ...entry.Values,\n }),\n );\n }\n\n return bidPackage;\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do nothing for updates\n return bidPackage;\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n const requirementId = entry.Values[nameof('id')];\n\n const matchingRequirementIndex = bidPackage.requirements.findIndex(\n (v) => v.id === requirementId,\n );\n\n if (matchingRequirementIndex > -1) {\n bidPackage.requirements.splice(matchingRequirementIndex, 1);\n }\n\n return bidPackage;\n },\n },\n\n BidPackageRequirementFulfillment: {\n onAdd: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by requirement ID, which is unique\n\n // Get requirement ID\n const requirementId = entry.Values[\n nameof('bidPackageRequirementId')\n ] as string;\n\n if (!requirementId) {\n return null;\n }\n\n // Create new requirement fulfillment\n const requirementFulfillment = new BidPackageRequirementFulfillment({ ...entry.Values });\n bidPackage.setRequirementFulfillment(requirementId, requirementFulfillment, true);\n\n // Return bid package\n return bidPackage;\n },\n onUpdate: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by requirement ID, which is unique\n\n // Get requirement and bidder IDs\n const requirementId = entry.Values[\n nameof('bidPackageRequirementId')\n ] as string;\n\n const bidderId = entry.Values['bidderId'] as string;\n if (!requirementId || !bidderId) {\n return null;\n }\n\n // Update requirement fulfillment\n const updatedRequirementFulfillment = new BidPackageRequirementFulfillment({\n ...bidPackage.getRequirementFulfillment(requirementId, bidderId), // Start with current entity values\n ...entry.Values, // Override with values provided in message\n });\n bidPackage.setRequirementFulfillment(requirementId, updatedRequirementFulfillment, true);\n\n // Return bid package\n return bidPackage;\n },\n onDelete: (bidPackage: BidPackage, entry: DataChangedEntry): BidPackage | null => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by requirement ID, which is unique\n\n // Get requirement and bidder IDs\n const requirementId = entry.Values[\n nameof('bidPackageRequirementId')\n ] as string;\n\n const bidderId = entry.Values['bidderId'] as string;\n if (!requirementId || !bidderId) {\n return null;\n }\n\n // Delete requirement fulfillment\n bidPackage.deleteRequirementFulfillment(requirementId, bidderId, true);\n\n // Return bid package\n return bidPackage;\n },\n },\n};\n\nexport default useBidPackage_ChangeNotifications;\n","import { clone } from 'lodash';\r\nimport { DeleteBidPackageLineItemCommand } from '../../../../../classes/commands/bid-packages/delete-bid-package-line-item-command';\r\nimport { UpdateBidPackageLineItemCommand } from '../../../../../classes/commands/bid-packages/update-bid-package-line-item-command';\r\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\r\nimport { normalizeNullOrUndefined } from '../../../../../utils/general';\r\n\r\ninterface ReturnValue {\r\n onChangeCallback_LineItem: (bidPackage: BidPackage, newLineItem: LineItemValue) => BidPackage;\r\n\r\n onBlurCallback_LineItem: (\r\n bidPackageCopy: BidPackage,\r\n currentBidPackage: BidPackage,\r\n updatedLineItem: LineItemValue,\r\n ) => ICommand | null;\r\n\r\n // Updates the bid package copy with the new data from the current bid package\r\n successFunction_LineItem: (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n\r\n // Updates the current bid package with the data from the bid package copy\r\n errorFunction_LineItem: (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n\r\n // Updates the bid package copy with the new data from the current bid package\r\n successFunction_LineItem_Delete: (\r\n commands: ICommand[],\r\n bidPackageToUpdate: BidPackage,\r\n ) => BidPackage;\r\n\r\n // Updates the current bid package with the data from the bid package copy\r\n errorFunction_LineItem_Delete: (\r\n commands: ICommand[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n ) => BidPackage;\r\n}\r\n\r\nconst useBidPackage_LineItems = (): ReturnValue => {\r\n return {\r\n onChangeCallback_LineItem,\r\n onBlurCallback_LineItem,\r\n successFunction_LineItem,\r\n errorFunction_LineItem,\r\n successFunction_LineItem_Delete,\r\n errorFunction_LineItem_Delete,\r\n };\r\n};\r\n\r\nconst onChangeCallback_LineItem = (\r\n bidPackage: BidPackage,\r\n newLineItem: LineItemValue,\r\n): BidPackage => {\r\n const currBidPackageCopy = clone(bidPackage);\r\n\r\n // Don't allow negative values because they bring us down\r\n if (currBidPackageCopy?.lineItems?.length) {\r\n const matchingLineItemIndex = currBidPackageCopy.lineItems.findIndex(\r\n (v) => v.id === newLineItem.id,\r\n );\r\n if (matchingLineItemIndex > -1) {\r\n const lineItemsCopy = [...currBidPackageCopy.lineItems];\r\n const lineItemCopy = clone(lineItemsCopy[matchingLineItemIndex]);\r\n\r\n lineItemCopy.quantity = newLineItem.quantity;\r\n lineItemCopy.quantityUnitOfMeasure = newLineItem.quantityUnitOfMeasure;\r\n lineItemCopy.unitPrice = newLineItem.unitPrice;\r\n\r\n lineItemsCopy[matchingLineItemIndex] = lineItemCopy;\r\n currBidPackageCopy.lineItems = lineItemsCopy;\r\n }\r\n }\r\n\r\n return currBidPackageCopy;\r\n};\r\n\r\nconst onBlurCallback_LineItem = (\r\n bidPackageCopy: BidPackage,\r\n currentBidPackage: BidPackage,\r\n updatedLineItem: LineItemValue,\r\n): ICommand | null => {\r\n // NOTE: We only ever update line items in this code, not adding or deleting\r\n const matchingLineItem = currentBidPackage.getLineItemById(updatedLineItem.id!);\r\n const matchingOriginalLineItem = bidPackageCopy.getLineItemById(updatedLineItem.id!);\r\n\r\n if (matchingLineItem && matchingOriginalLineItem) {\r\n const shouldUpdateLineItemQuantity =\r\n normalizeNullOrUndefined(matchingLineItem.quantity) !==\r\n normalizeNullOrUndefined(matchingOriginalLineItem.quantity);\r\n\r\n const shouldUpdateLineItemUnitOfMeasure =\r\n normalizeNullOrUndefined(matchingLineItem.quantityUnitOfMeasure) !==\r\n normalizeNullOrUndefined(matchingOriginalLineItem.quantityUnitOfMeasure);\r\n\r\n const shouldUpdateLineItemUnitPrice =\r\n normalizeNullOrUndefined(matchingLineItem.unitPrice) !==\r\n normalizeNullOrUndefined(matchingOriginalLineItem.unitPrice);\r\n\r\n if (\r\n shouldUpdateLineItemQuantity ||\r\n shouldUpdateLineItemUnitOfMeasure ||\r\n shouldUpdateLineItemUnitPrice\r\n ) {\r\n return new UpdateBidPackageLineItemCommand(\r\n currentBidPackage.id,\r\n updatedLineItem.id!,\r\n undefined,\r\n shouldUpdateLineItemQuantity ? updatedLineItem.quantity : undefined,\r\n shouldUpdateLineItemUnitOfMeasure ? updatedLineItem.quantityUnitOfMeasure : undefined,\r\n shouldUpdateLineItemUnitPrice ? updatedLineItem.unitPrice : undefined,\r\n );\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst successFunction_LineItem = (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n if (command instanceof UpdateBidPackageLineItemCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n const lineItem = copy.getLineItemById(command.lineItemId);\r\n\r\n if (lineItem) {\r\n const lineItemToAddOrUpdate = clone(\r\n bidPackageWithUpdatedData.getLineItemById(command.lineItemId),\r\n );\r\n\r\n if (lineItemToAddOrUpdate) {\r\n copy.setLineItem(lineItemToAddOrUpdate);\r\n }\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\nconst errorFunction_LineItem = (\r\n command: ICommand,\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n if (command instanceof UpdateBidPackageLineItemCommand) {\r\n const copy = clone(bidPackageToUpdate);\r\n const lineItemToRestore = clone(bidPackageWithUpdatedData.getLineItemById(command.lineItemId));\r\n\r\n if (lineItemToRestore) {\r\n copy.setLineItem(lineItemToRestore);\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\nconst successFunction_LineItem_Delete = (\r\n commands: ICommand[],\r\n bidPackageToUpdate: BidPackage,\r\n): BidPackage => {\r\n if (commands.every((v) => v instanceof DeleteBidPackageLineItemCommand)) {\r\n const copy = clone(bidPackageToUpdate);\r\n\r\n const commandsAsDeleteCommands = commands as DeleteBidPackageLineItemCommand[];\r\n const lineItemIdsToDelete = commandsAsDeleteCommands.map((v) => v.lineItemId);\r\n\r\n copy.lineItems = copy.lineItems.filter((v) => !lineItemIdsToDelete.includes(v.id!));\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\nconst errorFunction_LineItem_Delete = (\r\n commands: ICommand[],\r\n bidPackageToUpdate: BidPackage,\r\n bidPackageWithUpdatedData: BidPackage,\r\n): BidPackage => {\r\n if (commands.every((v) => v instanceof DeleteBidPackageLineItemCommand)) {\r\n const copy = clone(bidPackageToUpdate);\r\n\r\n const commandsAsDeleteCommands = commands as DeleteBidPackageLineItemCommand[];\r\n const lineItemIdsToRestore = commandsAsDeleteCommands.map((v) => v.lineItemId);\r\n\r\n copy.lineItems = [\r\n ...copy.lineItems,\r\n ...bidPackageWithUpdatedData.lineItems.filter((v) => lineItemIdsToRestore.includes(v.id!)),\r\n ];\r\n\r\n return copy;\r\n }\r\n\r\n return bidPackageToUpdate;\r\n};\r\n\r\nexport default useBidPackage_LineItems;\r\n","import { clone, sortBy } from 'lodash';\nimport { useCallback, useContext, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory } from 'react-router';\nimport { Alternate } from '../../../../../classes/odata/alternate';\nimport { Project } from '../../../../../classes/odata/project';\nimport ApplicationRoutes from '../../../../../constants/routes';\nimport { AuthenticationService } from '../../../../../services/authentication/authentication-service';\nimport { useLogger } from '../../../../../services/logger/Logger';\nimport { nameof } from '../../../../../utils/nameof';\nimport { areTrimmedStringsEqual } from '../../../../../utils/strings';\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\n\ninterface ReturnValue {\n projectChangeHandler: (message: DataChangedNotificationMessage) => Promise;\n}\n\ninterface DataChangeHandler {\n onAdd: (entry: DataChangedEntry, sourceId: string) => void;\n onUpdate: (entry: DataChangedEntry, sourceId: string) => void;\n onDelete: (entry: DataChangedEntry, sourceId: string) => void;\n}\n\nconst useProject_ChangeNotifications = (\n setProjectInfo: React.Dispatch>,\n): ReturnValue => {\n const logger = useLogger();\n const { t } = useTranslation();\n const history = useHistory();\n\n const { showErrorNotification, showInfoNotification } = useContext(NotificationPanelContext);\n\n const DataChangeHandlerMap: Record<\n DataChangedEntryTypes_BidPackagePage_Project,\n DataChangeHandler\n > = useMemo(\n () => ({\n Project: {\n onAdd: (entry: DataChangedEntry, sourceId: string): void => {\n // NOTE: We shouldn't get a change notification for an added project since\n // changes are scoped to a specific project\n },\n onUpdate: (entry: DataChangedEntry, sourceId: string): void => {\n setProjectInfo((currentProject) => {\n const updatedProject = new Project({\n ...currentProject,\n ...entry.Values,\n });\n\n return updatedProject;\n });\n },\n onDelete: (entry: DataChangedEntry, sourceId: string): void => {\n // NOTE: This is handled explicitly in projectChangeHandler\n },\n },\n Alternate: {\n onAdd: (entry: DataChangedEntry, sourceId: string): void => {\n setProjectInfo((currentProject) => {\n if (!currentProject) {\n return currentProject;\n }\n\n const projectClone = clone(currentProject);\n\n // Add alternate to clone and reassign\n const alternatesClone = [...projectClone.alternates];\n alternatesClone.push(\n new Alternate({\n ...entry.Values,\n }),\n );\n projectClone.alternates = sortAlternates(alternatesClone);\n\n return projectClone;\n });\n },\n onUpdate: (entry: DataChangedEntry, sourceId: string): void => {\n setProjectInfo((currentProject) => {\n if (!currentProject) {\n return currentProject;\n }\n\n const alternateId = entry.Values['id'] as string;\n const index = currentProject.alternates.findIndex((a) => a.id === alternateId);\n if (index === -1) {\n return currentProject;\n }\n\n const projectClone = clone(currentProject);\n\n // Update alternate from clone and reassign\n const alternatesClone = [...projectClone.alternates];\n alternatesClone[index] = new Alternate({\n ...projectClone.alternates[index],\n ...entry.Values,\n });\n projectClone.alternates = sortAlternates(alternatesClone);\n\n return projectClone;\n });\n },\n onDelete: (entry: DataChangedEntry, sourceId: string): void => {\n setProjectInfo((currentProject) => {\n if (!currentProject) {\n return currentProject;\n }\n\n const alternateId = entry.Values['id'] as string;\n const index = currentProject.alternates.findIndex((a) => a.id === alternateId);\n if (index === -1) {\n return currentProject;\n }\n\n const projectClone = clone(currentProject);\n\n // Delete alternate from clone and reassign\n const alternatesClone = [...projectClone.alternates];\n alternatesClone.splice(index, 1);\n projectClone.alternates = alternatesClone;\n\n return projectClone;\n });\n },\n },\n }),\n [setProjectInfo],\n );\n\n const projectChangeHandler = useCallback(\n (message: DataChangedNotificationMessage): Promise => {\n logger.logDebug('project.onDataChange', message);\n\n // Check to see if someone deleted the Project\n const deletedProjectEntry = message.Deleted.find((entry) => entry.Type === 'Project');\n if (deletedProjectEntry) {\n // Display error message\n const projectName = deletedProjectEntry.Values[nameof('name')] as string;\n showErrorNotification(\n t('general:error'),\n t('bid-summary:projectRemoved', { project: projectName, user: message.ChangedBy }),\n );\n\n // Return to home screen\n history.push(ApplicationRoutes.HOME);\n return Promise.reject();\n }\n\n // If this message closes the current project and isn't coming from the current user, we need to display a notification\n const closedProjectEntry = message.Updated.find(\n (entry) => entry.Type === 'Project' && entry.Values[nameof('isClosed')],\n );\n if (\n closedProjectEntry &&\n !areTrimmedStringsEqual(message.ChangedBy, AuthenticationService.currentUserInfo?.email)\n ) {\n // Display informational message\n showInfoNotification(t('project:projectClosed'), t('project:projectClosedMessage'));\n }\n\n message.Deleted.forEach((entry) => {\n const handler =\n DataChangeHandlerMap[entry.Type as DataChangedEntryTypes_BidPackagePage_Project];\n\n if (handler) {\n handler.onDelete(entry, message.SourceId);\n }\n });\n\n message.Updated.forEach((entry) => {\n const handler =\n DataChangeHandlerMap[entry.Type as DataChangedEntryTypes_BidPackagePage_Project];\n\n if (handler) {\n handler.onUpdate(entry, message.SourceId);\n }\n });\n\n message.Added.forEach((entry) => {\n const handler =\n DataChangeHandlerMap[entry.Type as DataChangedEntryTypes_BidPackagePage_Project];\n\n if (handler) {\n handler.onAdd(entry, message.SourceId);\n }\n });\n\n return Promise.resolve();\n },\n [DataChangeHandlerMap, history, logger, showErrorNotification, showInfoNotification, t],\n );\n\n return { projectChangeHandler };\n};\n\nconst sortAlternates = (alternates: Alternate[]): Alternate[] => {\n return sortBy(alternates, (a) => a.name);\n};\n\nexport default useProject_ChangeNotifications;\n","import { clone, cloneDeep, groupBy, isEqual, sortBy } from 'lodash';\nimport React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory, useLocation, useParams } from 'react-router';\nimport { Subscription } from 'rxjs';\nimport { AddLineItemToBidPackageCommand } from '../../../../classes/commands/bid-packages/add-line-item-to-bid-package-command';\nimport { ClearSelectedBidderOnBidPackage } from '../../../../classes/commands/bid-packages/clear-selected-bidder-on-bid-package-command';\nimport { DeleteBidPackageBidderCommand } from '../../../../classes/commands/bid-packages/delete-bid-package-bidder-command';\nimport { DeleteBidPackageLineItemCommand } from '../../../../classes/commands/bid-packages/delete-bid-package-line-item-command';\nimport { DeleteBidderRequirementFulfillmentOnBidPackageCommand } from '../../../../classes/commands/bid-packages/delete-bidder-requirement-fulfillment-on-bid-package-command';\nimport { DeleteLineItemBidOnBidPackageCommand } from '../../../../classes/commands/bid-packages/delete-line-item-bid-on-bid-package-command';\nimport { SetBidderOrderCommand } from '../../../../classes/commands/bid-packages/set-bidder-order-command';\nimport { SetBidderStatusCommand } from '../../../../classes/commands/bid-packages/set-bidder-status-command';\nimport { SetSelectedBidderOnBidPackage } from '../../../../classes/commands/bid-packages/set-selected-bidder-on-bid-package-command';\nimport { UpdateBidPackageLineItemCommand } from '../../../../classes/commands/bid-packages/update-bid-package-line-item-command';\nimport { UpdateBidPackageLineItemOrderCommand } from '../../../../classes/commands/bid-packages/update-bid-package-line-item-order-command';\nimport { UpdateBidPackageLineItemGroupOrderCommand } from '../../../../classes/commands/bid-packages/update-bid-package-line-item-group-order-command';\nimport { Adjustment } from '../../../../classes/odata/adjustment';\nimport { BidPackage } from '../../../../classes/odata/bid-package';\nimport { BidPackageBidTotal } from '../../../../classes/odata/bid-package-bid-total';\nimport { BidPackageLineItemBid } from '../../../../classes/odata/bid-package-line-item-bid';\nimport { BidPackageRequirementFulfillment } from '../../../../classes/odata/bid-package-requirement-fulfillment';\nimport { Bidder, BidderStatus } from '../../../../classes/odata/bidder';\nimport { Project } from '../../../../classes/odata/project';\nimport { UnitOfMeasure } from '../../../../classes/odata/unit-of-measure';\nimport BidPackageConstants from '../../../../constants/bid-package';\nimport ApplicationRoutes from '../../../../constants/routes';\nimport { useObservableWithValue } from '../../../../hooks/observables/useObservable';\nimport {\n BidPackageApi,\n FrozenEntitiesApi,\n ProjectApi,\n RecentProjectsApi,\n UserApi,\n} from '../../../../services';\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\nimport { useLogger } from '../../../../services/logger/Logger';\nimport { NotificationService } from '../../../../services/notification/notification-service';\nimport { ODataQueryBuilder } from '../../../../services/odata/bt-odata-service';\nimport { ODataHttpService } from '../../../../services/odata/odata-http-service';\nimport { normalizeNullOrUndefined } from '../../../../utils/general';\nimport { nameof } from '../../../../utils/nameof';\nimport {\n areTrimmedStringsEqual,\n doesStringExistInOtherString,\n getEmailWithoutDomain,\n} from '../../../../utils/strings';\nimport { generateUuid } from '../../../../utils/uuid';\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport { FloatingLoadingIndicatorContext } from '../../../common-page-components/floating-loading-indicator/FloatingLoadingIndicatorContext';\nimport { FormDropDownListOption } from '../../../common-page-components/forms/FormDropDownList';\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\nimport { BTGeneralContext } from '../../../common-page-components/general-contexts/BTGeneralContext';\nimport {\n BTGridContainerContext,\n BTGridContainerContextProvider,\n} from '../../../common-page-components/grid/grid-container/BTGridContainerContext';\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\nimport BTModal from '../../../common-page-components/modal/BTModal';\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\nimport { RequirementFulfillmentTypes } from '../../../enums/bid-package-enums';\nimport { useFeatureFlags } from '../../../feature-flagging/FeatureFlagContext';\nimport useCommandServiceHelper from '../../../shared-page-components/hooks/useCommandServiceHelper';\nimport useDegradedActionNotifications from '../../../shared-page-components/hooks/useDegradedActionNotifications';\nimport useProject_Info from '../../../shared-page-components/hooks/useProject_Info';\nimport BTGridContainer, {\n GridRerenderTrigger,\n} from './../../../common-page-components/grid/grid-container/BTGridContainer';\nimport './BidPackagePage.scss';\nimport useBidPackagePageContext, { BidPackagePageContextProvider } from './BidPackagePageContext';\nimport AddEditLineItemsForm, { LineItemInfo } from './components/AddEditLineItemsForm';\nimport BidPackageKeyboardShortcuts from './components/BidPackageKeyboardShortcuts';\nimport BidPackagePageHeader from './components/BidPackagePageHeader';\nimport useBidPackageBidHandler_Adjustments from './hooks/bid-handlers/useBidPackageBidHandler_Adjustments';\nimport useBidPackageBidHandler_LineItemBids from './hooks/bid-handlers/useBidPackageBidHandler_LineItemBids';\nimport useBidPackageBidHandler_LineItemRollupBids from './hooks/bid-handlers/useBidPackageBidHandler_LineItemRollupBids';\nimport useBidPackageBidHandler_RequirementFulfillments from './hooks/bid-handlers/useBidPackageBidHandler_RequirementFulfillments';\nimport useBidPackage from './hooks/useBidPackage';\nimport useBidPackageAdjustments_Notes from './hooks/useBidPackageAdjustments_Notes';\nimport useBidPackageBidders_AddEditForm from './hooks/useBidPackageBidders_AddEditForm';\nimport useBidPackageBidders_DocumentsModal from './hooks/useBidPackageBidders_DocumentsModal';\nimport useBidPackageBidders_InfoModal from './hooks/useBidPackageBidders_InfoModal';\nimport useBidPackageBidders_Notes from './hooks/useBidPackageBidders_Notes';\nimport useBidPackageGrid_Adjustments from './hooks/useBidPackageGrid_Adjustments';\nimport useBidPackageGrid_Header from './hooks/useBidPackageGrid_Header';\nimport useBidPackageGrid_LineItems from './hooks/useBidPackageGrid_LineItems';\nimport useBidPackageGrid_LineItems_Alternates from './hooks/useBidPackageGrid_LineItems_Alternates';\nimport useBidPackageGrid_LineItems_Header from './hooks/useBidPackageGrid_LineItems_Header';\nimport useBidPackageGrid_Requirements from './hooks/useBidPackageGrid_Requirements';\nimport useBidPackage_ChangeNotifications from './hooks/useBidPackage_ChangeNotifications';\nimport useBidPackage_LineItems from './hooks/useBidPackage_LineItems';\nimport useProject_ChangeNotifications from './hooks/useProject_ChangeNotifications';\n\ninterface RouteParams {\n bidPackageId: string;\n projectId: string;\n}\n\ninterface LineItemsModalState {\n isOpen: boolean;\n mode: 'add' | 'edit';\n}\n\ninterface BidPackagePageNotification {\n type: 'project' | 'bid package';\n notification: DataChangedNotificationMessage | EntityFrozenNotificationMessage;\n}\n\nconst lineItemTypeString: DataChangedEntryTypes_BidPackagePage_BidPackage = 'BidPackageLineItem';\nconst lineItemGroupOrderTypeString: DataChangedEntryTypes_BidPackagePage_BidPackage =\n 'BidPackageLineItemGroupOrder';\nconst bidPackageTypeString: DataChangedEntryTypes_BidPackagePage_BidPackage = 'BidPackage';\nconst bidderTypeString: DataChangedEntryTypes_BidPackagePage_BidPackage = 'Bidder';\nconst bidderFileUploadTypeString: DataChangedEntryTypes_BidPackagePage_BidPackage =\n 'BidderFileUpload';\n\n// NOTE: This component is wrapped by another component that provides it with a context and that\n// component is what is exposed from this file\nconst BidPackagePageInternalComponent: React.FC = () => {\n const isInitialDataLoadComplete = useRef(false);\n const notificationsReceivedDuringInitialDataLoad = useRef([]);\n const [liveUpdateRegistrationFailed, setLiveUpdateRegistrationFailed] = useState(false);\n const [projectId, setProjectId] = useState(null);\n const [projectInfo, setProjectInfo] = useState(null);\n const [projectDetailInfo, setProjectDetailInfo] = useState(null);\n const addEditLineItemsFormIsDirty = useRef(false);\n\n const [keyboardShortcutsInfoIsOpen, setKeyboardShortcutsInfoIsOpen] = useState(false);\n\n const [\n lastEditedBidderForBidderNotes,\n setLastEditedBidderForBidderNotes,\n ] = useState(null);\n\n const [\n lastEditedAdjustmentForAdjustmentNotes,\n setLastEditedAdjustmentForAdjustmentNotes,\n ] = useState(null);\n\n const [lineItemsModalState, setLineItemsModalState] = useState({\n isOpen: false,\n mode: 'add',\n });\n\n const [alternateToAddLineItemsTo, setAlternateToAddLineItemsTo] = useState(null);\n const [bidderForDocumentsModal, setBidderForDocumentsModal] = useState(null);\n\n // A timeout that we use for all of the input fields when we want to auto-save after a specified timeout\n const autoSaveTimeout = useRef(null);\n\n const { t } = useTranslation();\n const currentUser = AuthenticationService.currentUserInfo;\n const logger = useLogger();\n const history = useHistory();\n const routeParams = useParams();\n const location = useLocation();\n const { featureIsEnabled } = useFeatureFlags();\n\n const { showErrorNotification, showInfoNotification, showSuccessNotification } = useContext(\n NotificationPanelContext,\n );\n\n const { signalRResponseTimeout } = useContext(BTGeneralContext);\n\n const { selectedRowsChange$, itemsReordered$ } = useContext(BTGridContainerContext);\n\n const {\n // Observables\n adjustmentBlur$,\n adjustmentChange$,\n adjustmentNotesOpen$,\n adjustmentNotesSave$,\n\n bidderDelete$,\n bidderEdit$,\n bidderEditDocuments$,\n bidderEditNotes$,\n bidderSelect$,\n bidderShowInfo$,\n biddersAdd$,\n\n lineItemBlur$,\n lineItemChange$,\n lineItemsAdd$,\n lineItemEdit$,\n lineItemsEdit$,\n lineItemDelete$,\n lineItemsDelete$,\n\n lineItemBidBlur$,\n lineItemBidChange$,\n lineItemBidFocus$,\n\n lineItemRollupBidBlur$,\n lineItemRollupBidChange$,\n\n requirementFulfillmentBlur$,\n requirementFulfillmentChange$,\n requirementFulfillmentFocus$,\n\n // Other observables\n bidPackageNotes$,\n keyboardShortcutsInfoIsOpen$,\n lockBidPackage$,\n selectedLineItemsMappings$,\n viewProjectInfo$,\n\n // Functions\n adjustment_Blur,\n adjustment_Change,\n lineItemBid_Blur,\n lineItemRollupBid_Blur,\n lineItem_Blur,\n requirementFulfillment_Blur,\n selectedLineItemsMappings_Change,\n } = useBidPackagePageContext();\n\n const { editAdjustmentNotes, getAdjustmentNotesJSX } = useBidPackageAdjustments_Notes();\n\n const { hidePageLoadingOverlay, showPageLoadingOverlay } = useContext(LoadingPageOverlayContext);\n\n const { showFloatingLoadingIndicator_Green, hideFloatingLoadingIndicator_Green } = useContext(\n FloatingLoadingIndicatorContext,\n );\n\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n\n const [signalRBroadcast_Project$, onSignalRBroadcast_Project] = useObservableWithValue<\n DataChangedNotificationMessage | EntityFrozenNotificationMessage\n >();\n\n const [signalRBroadcast_BidPackage$, onSignalRBroadcast_BidPackage] = useObservableWithValue<\n DataChangedNotificationMessage | EntityFrozenNotificationMessage\n >();\n\n const [allBidPackageDropdownOptions, setAllBidPackageDropdownOptions] = useState<\n FormDropDownListOption[]\n >([]);\n\n const [allUnitOfMeasureDropdownOptions, setAllUnitOfMeasureDropdownOptions] = useState(\n [],\n );\n\n const [selectedBidPackageId, setSelectedBidPackageId] = useState(null);\n\n const [selectedBidPackage, setSelectedBidPackage] = useState();\n\n // Holds a version of the bid package that we can use to determine which commands to generate\n const selectedBidPackage_Staging = useRef();\n\n // Holds a version of the bid package that is based on committed commands data\n const selectedBidPackage_Committed = useRef();\n\n const [lockedByUser, setLockedByUser] = useState();\n\n // A copy of the selected line items for each \"section\" (ie. main section or specific alternate sections)\n const selectedLineItemsMappingsCopy = useRef>({});\n\n const [lineItemsToEdit, setLineItemsToEdit] = useState([]);\n\n const { executeCommand } = useCommandServiceHelper();\n\n const { projectChangeHandler } = useProject_ChangeNotifications(setProjectInfo);\n const { executeBidPackageChangeHandler } = useBidPackage_ChangeNotifications();\n\n const lastFocusedLineItemBidInfo = useRef<{\n bidPackageLineItemId: string;\n bidderId: string;\n } | null>(null);\n\n const lastFocusedRequirementFulfillmentBidInfo = useRef<{\n requirementId: string;\n bidderId: string;\n } | null>(null);\n\n const lineItemBlurTimeout = useRef(null);\n const requirementFulfillmentBlurTimeout = useRef(null);\n\n const isProjectAdmin = doesStringExistInOtherString(\n projectInfo?.projectAdmins,\n currentUser!.email,\n );\n const isUserAssignedContributor = selectedBidPackage?.assignedToUserId === currentUser!.id;\n\n const [bidPackageIsFrozen, setBidPackageIsFrozen] = useState(false);\n const [bidPackageNotesAreFrozen, setBidPackageNotesAreFrozen] = useState(false);\n const [bidderNoteIdsThatAreFrozen, setBidderNoteIdsThatAreFrozen] = useState([]);\n const [bidderFileUploadContainerIdsThatAreFrozen, setBidderFileUploadIdsThatAreFrozen] = useState<\n string[]\n >([]);\n const [adjustmentNoteIdsThatAreFrozen, setAdjustmentNoteIdsThatAreFrozen] = useState(\n [],\n );\n\n const isReadOnly = useMemo((): boolean => {\n if (liveUpdateRegistrationFailed) {\n return true;\n }\n\n if (bidPackageIsFrozen) {\n return true;\n }\n\n // If the project is in a closed state, set read-only\n if (projectInfo?.isClosed) {\n return true;\n }\n\n // If the current user is not a contributor or projectAdmin for the project, set read-only\n const isContributor = doesStringExistInOtherString(\n projectInfo?.contributors,\n currentUser!.email,\n );\n\n if (!(isContributor || isProjectAdmin)) {\n return true;\n }\n\n // If the bid package is locked\n if (selectedBidPackage?.lockedByUserEmail) {\n // Check if the lock is held by a projectAdmin\n const isLockedByProjectAdmin = projectInfo?.projectAdmins?.includes(\n selectedBidPackage.lockedByUserEmail,\n );\n\n // If the lock is held by a projectAdmin\n if (isLockedByProjectAdmin) {\n // If the user is not also a projectAdmin, set read-only\n if (!isProjectAdmin) {\n return true;\n }\n } else {\n // Else the lock is held by the assigned contributor, so if the user is not the assignedContributor or a projectAdmin, set read-only\n if (!(isUserAssignedContributor || isProjectAdmin)) {\n return true;\n }\n }\n }\n\n return false;\n }, [\n currentUser,\n projectInfo,\n selectedBidPackage,\n isProjectAdmin,\n isUserAssignedContributor,\n bidPackageIsFrozen,\n liveUpdateRegistrationFailed,\n ]);\n\n const canLockBidPackage = !(isReadOnly || !(isUserAssignedContributor || isProjectAdmin));\n\n const projectNotificationHandler = useCallback(\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\n // We do not do anything on the Bid Package page when the project is frozen\n if (message.hasOwnProperty(nameof('IsFrozen'))) {\n return;\n }\n\n const messageAsDataChangedMessage = message as DataChangedNotificationMessage;\n projectChangeHandler(messageAsDataChangedMessage);\n\n // Check to see if the project admins changed for the project\n const updatedProjectAdminsMessages = messageAsDataChangedMessage.Updated.filter(\n (v) =>\n v.Type === ('Project' as DataChangedEntryTypes_BidPackagePage_Project) &&\n v.Values[nameof('projectAdmins')] !== undefined,\n );\n\n if (updatedProjectAdminsMessages.length > 0) {\n const projectAdminsChangedValues = updatedProjectAdminsMessages\n .map((v) => v.Values[nameof('projectAdmins')] || '')\n .filter((v) => v) as string[];\n\n // If the page is currently read only and the user is about to become a project admin, or vice versa, we need to rerender the grid\n // because the available columns will change (the column for the checkboxes on line item rows, in particular)\n if (\n (isReadOnly &&\n projectAdminsChangedValues.some((v) =>\n doesStringExistInOtherString(v, currentUser!.email),\n )) ||\n (!isReadOnly &&\n !projectAdminsChangedValues.some((v) =>\n doesStringExistInOtherString(v, currentUser!.email),\n ))\n ) {\n // NOTE: On the bid package page, we don't change the columns of the primary grid\n setGridRerenderTriggerObject({\n rowsChanged: true,\n primaryGridColumnsChanged: true,\n });\n }\n }\n\n // Refresh the grid when certain things happen that can affect the rows or columns we display\n const typesToCheck: DataChangedEntryTypes_BidPackagePage_Project[] = ['Alternate'];\n\n if (\n messageAsDataChangedMessage.Added.concat(messageAsDataChangedMessage.Deleted).some((v) =>\n (typesToCheck as string[]).includes(v.Type),\n )\n ) {\n // NOTE: On the bid package page, we don't change the columns of the primary grid\n setGridRerenderTriggerObject({\n rowsChanged: true,\n });\n }\n\n const addedBidPackagesDropdownOptions = messageAsDataChangedMessage.Added.filter(\n (v) => v.Type === 'BidPackage',\n ).map(\n (v): FormDropDownListOption => {\n const bidPackageId = v.Values[nameof('id')] as string;\n const bidPackageCode = v.Values[nameof('code')] as string;\n const bidPackageDescription = v.Values[nameof('description')] as string;\n\n return {\n name: `${bidPackageCode} - ${bidPackageDescription}`,\n value: bidPackageId,\n };\n },\n );\n\n const deletedBidPackageIds = messageAsDataChangedMessage.Deleted.filter(\n (v) => v.Type === 'BidPackage',\n ).map((v) => v.Values[nameof('id')] as string);\n\n // Update the dropdown options\n const newDropdownOptions = sortBy(\n allBidPackageDropdownOptions\n .filter((v) => !deletedBidPackageIds.includes(v.value))\n .concat(addedBidPackagesDropdownOptions),\n (v) => v.name,\n );\n\n setAllBidPackageDropdownOptions(newDropdownOptions);\n\n // If a bid package was deleted out from under us, show a message and\n // select the first bid package in the dropdown\n messageAsDataChangedMessage.Deleted.forEach((entry: DataChangedEntry) => {\n if (entry.Type === 'BidPackage') {\n const deletedBidPackageId = entry.Values[nameof('id')] as string;\n\n if (deletedBidPackageId === selectedBidPackageId) {\n // Set selected bid package to first in collection\n setSelectedBidPackageId(newDropdownOptions[0]?.value ?? null);\n\n // Notify user of removed bid package\n showInfoNotification(\n t('general:info'),\n t('bid-package:bidPackageRemoved', {\n bidPackageDescription: selectedBidPackage?.description,\n }),\n );\n }\n }\n });\n },\n [\n projectChangeHandler,\n allBidPackageDropdownOptions,\n isReadOnly,\n currentUser,\n selectedBidPackage?.description,\n selectedBidPackageId,\n showInfoNotification,\n t,\n ],\n );\n\n const bidPackageNotificationHandler = useCallback(\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\n try {\n showFloatingLoadingIndicator_Green(t('general:syncing'));\n\n // NOTE: We get notified when an entity gets frozen, but NOT unfrozen, so we just want to update the\n // various state variables as to what is now frozen.\n if (message.hasOwnProperty(nameof('IsFrozen'))) {\n logger.logDebug(`bidPackage.onFrozenEntityNotification: ${JSON.stringify(message)}`);\n const entityFrozenMessage = message as EntityFrozenNotificationMessage;\n\n const bidderNoteIds = selectedBidPackage!.bidders\n .map((v) => v.notesId?.toLowerCase() || '')\n .filter((v) => v);\n\n const adjustmentNoteIds = selectedBidPackage!.adjustments\n .map((v) => v.notesId?.toLowerCase() || '')\n .filter((v) => v);\n\n const bidderFileUploadContainerIds = selectedBidPackage!.bidders\n .map((v) => v.fileUploadContainerId?.toLowerCase() || '')\n .filter((v) => v);\n\n if (entityFrozenMessage.IsFrozen) {\n // Set frozen entities in state\n if (entityFrozenMessage.SourceId === selectedBidPackageId?.toLowerCase()) {\n setBidPackageIsFrozen(true);\n } else if (\n entityFrozenMessage.SourceId === selectedBidPackage?.notesId?.toLowerCase()\n ) {\n setBidPackageNotesAreFrozen(true);\n } else if (bidderNoteIds.includes(entityFrozenMessage.SourceId)) {\n setBidderNoteIdsThatAreFrozen((v) => {\n return [...v, entityFrozenMessage.SourceId];\n });\n } else if (adjustmentNoteIds.includes(entityFrozenMessage.SourceId)) {\n setAdjustmentNoteIdsThatAreFrozen((v) => {\n return [...v, entityFrozenMessage.SourceId];\n });\n } else if (bidderFileUploadContainerIds.includes(entityFrozenMessage.SourceId)) {\n setBidderFileUploadIdsThatAreFrozen((v) => {\n return [...v, entityFrozenMessage.SourceId];\n });\n }\n } else {\n // TODO: Unfreeze entities\n // NOTE: As-is we have no way to send an \"unfrozen\" message so there's no way to test\n }\n\n return;\n }\n\n logger.logDebug(`bidPackage.onDataChange: ${JSON.stringify(message)}`);\n\n const messageAsDataChangedMessage = message as DataChangedNotificationMessage;\n\n // When certain things change that can affect the bid totals, we want to get the updated values\n let bidPackageTotals: BidPackageBidTotal[] | null = null;\n\n const dataChangedEntryTypesThatCanAffectTotals: DataChangedEntryTypes_BidPackagePage_BidPackage[] = [\n 'Adjustment',\n 'Bidder',\n 'BidPackageLineItem',\n 'BidPackageLineItemBid',\n 'BidPackageLineItemRollupBid',\n 'BidPackageRequirementFulfillment',\n ];\n\n if (\n messageAsDataChangedMessage.Added.concat(messageAsDataChangedMessage.Updated)\n .concat(messageAsDataChangedMessage.Deleted)\n .some((v) =>\n dataChangedEntryTypesThatCanAffectTotals.includes(\n v.Type as DataChangedEntryTypes_BidPackagePage_BidPackage,\n ),\n )\n ) {\n bidPackageTotals = await BidPackageApi.getBidPackageTotals(selectedBidPackageId!);\n }\n\n const applyBidPackageChanges = (\n bidPackageToUpdate: BidPackage | undefined,\n runChangeHandlerCompleteCallbacks: boolean,\n ): BidPackage | undefined => {\n if (!bidPackageToUpdate) {\n return bidPackageToUpdate;\n }\n\n // Make a shallow copy of the bid package we are mutating\n let updatedBidPackage = clone(bidPackageToUpdate);\n\n // Process deleted entities\n messageAsDataChangedMessage.Deleted.forEach((entry: DataChangedEntry) => {\n let onChangeHandlerCompleteCallback: ((bidPackage2: BidPackage) => void) | undefined;\n\n switch (entry.Type) {\n case bidPackageTypeString:\n onChangeHandlerCompleteCallback = (bidPackage2: BidPackage) => {\n const updateProjectBidPackageCollection = (): Project | null => {\n if (!projectInfo) {\n return null;\n }\n\n // Get the index of the selected bid package\n const bidPackageIndex = projectInfo.bidPackages.findIndex(\n (bp: BidPackage) => bp.id === selectedBidPackageId,\n );\n\n // If the bid package isn't on the project, there's nothing to update\n if (bidPackageIndex === -1) {\n return projectInfo;\n }\n\n const projectClone = clone(projectInfo);\n\n // Remove bid package from array\n projectClone.bidPackages.splice(bidPackageIndex, 1);\n\n return projectClone;\n };\n\n const updatedProject = updateProjectBidPackageCollection();\n setProjectInfo(updatedProject);\n\n const deletedBidPackageId = entry.Values[nameof('id')] as string;\n if (deletedBidPackageId === selectedBidPackageId) {\n // Set selected bid package to first in collection\n const firstBidPackage = updatedProject?.bidPackages[0];\n setSelectedBidPackageId(firstBidPackage?.id ?? null);\n setSelectedBidPackage(firstBidPackage);\n\n // Notify user of removed bid package\n showInfoNotification(\n t('general:info'),\n t('bid-package:bidPackageRemoved', {\n bidPackageDescription: bidPackage2.description,\n }),\n );\n }\n };\n break;\n }\n\n updatedBidPackage =\n executeBidPackageChangeHandler(updatedBidPackage, 'delete', entry) ||\n updatedBidPackage;\n\n if (runChangeHandlerCompleteCallbacks && onChangeHandlerCompleteCallback) {\n onChangeHandlerCompleteCallback(updatedBidPackage);\n }\n });\n\n // Process added entities\n messageAsDataChangedMessage.Added.forEach((entry: DataChangedEntry) => {\n switch (entry.Type) {\n case bidderFileUploadTypeString:\n hidePageLoadingOverlay();\n break;\n }\n\n updatedBidPackage =\n executeBidPackageChangeHandler(updatedBidPackage, 'add', entry) || updatedBidPackage;\n });\n\n // Process updated entities\n messageAsDataChangedMessage.Updated.forEach((entry: DataChangedEntry) => {\n let onChangeHandlerCompleteCallback: ((bidPackage2: BidPackage) => void) | undefined;\n\n switch (entry.Type) {\n // if a Bidder was updated (ex: a document was uploaded, which triggered Bidder.FileUploadContainerId to be populated),\n // update the bidderForDocumentsModal Bidder state variable with the new data.\n case bidderTypeString:\n onChangeHandlerCompleteCallback = (bidPackage2: BidPackage) => {\n if (bidPackage2) {\n setBidderForDocumentsModal((currentBidder) => {\n if (!currentBidder) {\n return null;\n }\n return bidPackage2.bidders.find((b) => b.id === currentBidder.id) || null;\n });\n }\n };\n break;\n }\n\n updatedBidPackage =\n executeBidPackageChangeHandler(updatedBidPackage, 'update', entry) ||\n updatedBidPackage;\n\n if (runChangeHandlerCompleteCallbacks && onChangeHandlerCompleteCallback) {\n onChangeHandlerCompleteCallback(updatedBidPackage);\n }\n });\n\n if (bidPackageTotals) {\n updatedBidPackage.bidTotals = bidPackageTotals;\n }\n\n return updatedBidPackage;\n };\n\n // NOTE: We must apply the changes individually to each bid package copy so the same changes\n // are replicated but the data remains siloed.\n\n const previousLineItemsCount = selectedBidPackage_Committed.current?.lineItems.length;\n // Apply changes to committed bid package ref\n selectedBidPackage_Committed.current = applyBidPackageChanges(\n selectedBidPackage_Committed.current,\n false,\n );\n\n // Apply changes to staging bid package ref\n selectedBidPackage_Staging.current = applyBidPackageChanges(\n selectedBidPackage_Staging.current,\n false,\n );\n\n // Apply changes to bid package state.\n // NOTE: By using the state setter callback syntax, we will always be operating on up-to-date bid package values.\n setSelectedBidPackage((currentBidPackage) => {\n const updatedBidPackage = applyBidPackageChanges(currentBidPackage, true);\n return updatedBidPackage;\n });\n\n // In certain situations, we want to re-render the grid, which will kick off row height calculations, among other things.\n // This is a significant performance hit on pages with a lot of data so we only do it when we absolutely have to.\n // For certain things like bidders being deleted, that doesn't affect row heights aside from potentially the main bidder\n // column header row shrinking, so it isn't worth the performance hit to rerun grid calculations when things won't actively look worse\n // if they're slightly too tall.\n if (\n messageAsDataChangedMessage.Added.concat(messageAsDataChangedMessage.Deleted)\n .concat(messageAsDataChangedMessage.Updated)\n .some((v) => v.Type === lineItemTypeString) ||\n messageAsDataChangedMessage.Added.concat(messageAsDataChangedMessage.Deleted).some(\n (v) => v.Type === lineItemGroupOrderTypeString,\n ) ||\n messageAsDataChangedMessage.Added.concat(messageAsDataChangedMessage.Updated).some(\n (v) => v.Type === bidderTypeString,\n )\n ) {\n setGridRerenderTriggerObject({\n rowsChanged: true,\n });\n }\n\n // If the message was triggered by something the current user did and we have an active\n // signal R response timeout, it means we are waiting for a SignalR event for whatever we just did\n if (\n areTrimmedStringsEqual(\n messageAsDataChangedMessage.ChangedBy,\n AuthenticationService.currentUserInfo?.email,\n ) &&\n signalRResponseTimeout.current\n ) {\n clearTimeout(signalRResponseTimeout.current);\n signalRResponseTimeout.current = null;\n\n // show appropriate messages for updates to the lineItems and bidders\n const messageAsDataChangedMessage = message as DataChangedNotificationMessage;\n if (messageAsDataChangedMessage.Added.length > 0) {\n // line item or bidder added\n if (messageAsDataChangedMessage.Added[0].Type === lineItemTypeString) {\n if (previousLineItemsCount === 0) {\n // Refresh the grid\n setGridRerenderTriggerObject({\n // NOTE: On the bid package page, we don't change the columns of the primary grid\n rowsChanged: true,\n primaryGridColumnsChanged: true,\n });\n }\n showSuccessNotification(\n t('general:success'),\n t('bid-package:addEditLineItemsSuccess'),\n );\n } else if (messageAsDataChangedMessage.Added[0].Type === bidderTypeString) {\n showSuccessNotification(t('general:success'), t('bid-package:addBiddersSuccess'));\n }\n }\n\n if (messageAsDataChangedMessage.Updated.length > 0) {\n // line item or bidder updated\n if (messageAsDataChangedMessage.Updated[0].Type === lineItemTypeString) {\n showSuccessNotification(\n t('general:success'),\n t('bid-package:addEditLineItemsSuccess'),\n );\n } else if (messageAsDataChangedMessage.Updated[0].Type === bidderTypeString) {\n showSuccessNotification(t('general:success'), t('bid-package:editBidderSuccess'));\n }\n }\n\n if (messageAsDataChangedMessage.Deleted.length > 0) {\n // line item or bidder deleted\n if (messageAsDataChangedMessage.Deleted[0].Type === lineItemTypeString) {\n showSuccessNotification(\n t('general:success'),\n t('bid-package:deleteLineItemsSuccess'),\n );\n } else if (messageAsDataChangedMessage.Deleted[0].Type === bidderTypeString) {\n showSuccessNotification(t('general:success'), t('bid-package:deleteBidderSuccess'));\n }\n }\n\n hidePageLoadingOverlay(true);\n }\n } finally {\n // Delay turning off the loading indicator slightly, since this code can run very fast at times\n // and we don't want things to flicker too fast where the user doesn't see it (it's beautiful and\n // deserves to be seen, dammit)\n setTimeout(() => {\n hideFloatingLoadingIndicator_Green();\n }, 500);\n }\n },\n [\n executeBidPackageChangeHandler,\n hideFloatingLoadingIndicator_Green,\n hidePageLoadingOverlay,\n logger,\n projectInfo,\n selectedBidPackage,\n selectedBidPackageId,\n showFloatingLoadingIndicator_Green,\n showInfoNotification,\n showSuccessNotification,\n signalRResponseTimeout,\n t,\n ],\n );\n\n useDegradedActionNotifications('BidPackagePage');\n\n // Initial data load\n useEffect(() => {\n const loadInitialData = async (): Promise => {\n if (isInitialDataLoadComplete.current) {\n return;\n }\n\n try {\n showPageLoadingOverlay();\n\n const query = new URLSearchParams(location.search);\n\n if (routeParams.bidPackageId) {\n const projectInformation = await ProjectApi.getProjectInfoForBidPackage(\n routeParams.bidPackageId,\n );\n\n if (!projectInformation) {\n throw new Error(t('bid-package:projectInfoNotFoundError', { id: projectId }));\n }\n\n setProjectId(projectInformation.id!);\n setProjectInfo(projectInformation);\n } else {\n // if the projectId route parameter is provided, use it. Otherwise default to no selected project.\n const projectIdFromQueryString = query.get('projectId');\n if (projectIdFromQueryString) {\n setProjectId(projectIdFromQueryString);\n }\n }\n\n const [bidPackagesData, unitsOfMeasure] = await Promise.all([\n BidPackageApi.getBidPackagesForProject(projectId!),\n ODataHttpService.toArray(\n new ODataQueryBuilder(UnitOfMeasure).getQueryObject(),\n ),\n ]);\n\n if (!bidPackagesData.length) {\n setAllBidPackageDropdownOptions([\n {\n name: t('bid-package:noBidPackages'),\n value: null,\n },\n ]);\n setSelectedBidPackageId(null);\n return;\n }\n\n const unitOfMeasureDropdownOptions: string[] = sortBy(\n (unitsOfMeasure as UnitOfMeasure[]).map((v) => v.name!),\n (v) => v,\n );\n\n const bidPackageDropdownOptions: FormDropDownListOption[] = sortBy(\n (bidPackagesData as BidPackageInfo[]).map((v) => ({\n name: `${v.code} - ${v.description}`,\n value: v.id,\n })),\n (v) => v.name,\n );\n\n setAllUnitOfMeasureDropdownOptions(unitOfMeasureDropdownOptions);\n setAllBidPackageDropdownOptions(bidPackageDropdownOptions);\n\n const bidPackageId = routeParams.bidPackageId ?? bidPackageDropdownOptions[0].value;\n setSelectedBidPackageId(bidPackageId);\n\n // Process any notifications we received during the initial data load\n for (const msg of notificationsReceivedDuringInitialDataLoad.current) {\n if (msg.type === 'project') {\n await projectNotificationHandler(msg.notification);\n } else if (msg.type === 'bid package') {\n await bidPackageNotificationHandler(msg.notification);\n }\n }\n notificationsReceivedDuringInitialDataLoad.current = [];\n\n isInitialDataLoadComplete.current = true;\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('bid-package:loadBidPackagesError'));\n history.push(ApplicationRoutes.ERROR_ERROR);\n } finally {\n hidePageLoadingOverlay();\n }\n };\n\n loadInitialData();\n }, [\n setProjectId,\n setProjectInfo,\n projectId,\n showPageLoadingOverlay,\n history,\n location,\n routeParams.bidPackageId,\n setSelectedBidPackageId,\n t,\n logger,\n showErrorNotification,\n hidePageLoadingOverlay,\n projectNotificationHandler,\n bidPackageNotificationHandler,\n ]);\n\n // Updates lockedByUser when selectedBidPackage.lockedByUserEmail changes\n const lockedByUserEmail = selectedBidPackage?.lockedByUserEmail;\n useEffect(() => {\n const updateLockedByUser = async () => {\n const user = !lockedByUserEmail ? null : await UserApi.getUserByEmail(lockedByUserEmail);\n setLockedByUser(user ?? undefined);\n };\n\n updateLockedByUser();\n }, [lockedByUserEmail]);\n\n const loadProjectDetailInfo = useCallback(async (): Promise => {\n if (projectId) {\n const projectInformation = await ProjectApi.getProjectInfoById(projectId);\n setProjectDetailInfo(projectInformation);\n return projectInformation;\n } else {\n return null;\n }\n }, [projectId, setProjectDetailInfo]);\n\n const loadBidPackageDetails = useCallback(async () => {\n if (!selectedBidPackageId) {\n return;\n }\n\n try {\n showPageLoadingOverlay();\n\n const bidPackagesObj = await BidPackageApi.getBidPackageById(selectedBidPackageId);\n\n if (!bidPackagesObj) {\n throw new Error(`Failed to load bid package with ID '${selectedBidPackageId}'`);\n }\n\n // Get the frozen status for the bid package / bid package notes\n const [bidPackageIsFrozen, bidPackageNotesAreFrozen] = await Promise.all([\n FrozenEntitiesApi.checkIfEntityIsFrozen(selectedBidPackageId),\n bidPackagesObj.notesId\n ? FrozenEntitiesApi.checkIfEntityIsFrozen(bidPackagesObj.notesId)\n : Promise.resolve(false),\n ]);\n\n // Get the frozen status for any bidder notes\n const bidderNoteIds = bidPackagesObj!.bidders.map((v) => v.notesId || '').filter((v) => v);\n\n const bidderNotesPromisesArray: Promise[] = bidderNoteIds.map((currBidderNoteId) =>\n FrozenEntitiesApi.checkIfEntityIsFrozen(currBidderNoteId),\n );\n\n const bidderNoteIdsResults = await Promise.all(bidderNotesPromisesArray);\n const frozenBidderNoteIds: string[] = [];\n\n bidderNoteIdsResults.forEach((v, i) => {\n if (v) {\n frozenBidderNoteIds.push(bidderNoteIds[i]);\n }\n });\n\n // Get the frozen status for any adjustment notes\n const adjustmentNoteIds = bidPackagesObj!.adjustments\n .map((v) => v.notesId || '')\n .filter((v) => v);\n\n const adjustmentNotesPromisesArray: Promise<\n boolean\n >[] = adjustmentNoteIds.map((currBidderNoteId) =>\n FrozenEntitiesApi.checkIfEntityIsFrozen(currBidderNoteId),\n );\n\n const adjustmentNoteIdsResults = await Promise.all(adjustmentNotesPromisesArray);\n const frozenAdjustmentNoteIds: string[] = [];\n\n adjustmentNoteIdsResults.forEach((v, i) => {\n if (v) {\n frozenAdjustmentNoteIds.push(adjustmentNoteIds[i]);\n }\n });\n\n // Get the frozen status of bidder documents\n const bidderFileUploadContainerIds = bidPackagesObj!.bidders\n .map((v) => v.fileUploadContainerId || '')\n .filter((v) => v);\n\n const bidderFileUploadContainerPromisesArray: Promise<\n boolean\n >[] = bidderFileUploadContainerIds.map((currFileUploadContainerId) =>\n FrozenEntitiesApi.checkIfEntityIsFrozen(currFileUploadContainerId),\n );\n\n const bidderFileUploadContainerIdsResults = await Promise.all(\n bidderFileUploadContainerPromisesArray,\n );\n const frozenBidderFileUploadContainerIds: string[] = [];\n\n bidderFileUploadContainerIdsResults.forEach((v, i) => {\n if (v) {\n frozenBidderFileUploadContainerIds.push(bidderFileUploadContainerIds[i]);\n }\n });\n\n setBidPackageIsFrozen(bidPackageIsFrozen);\n setBidPackageNotesAreFrozen(bidPackageNotesAreFrozen);\n setBidderNoteIdsThatAreFrozen(frozenBidderNoteIds);\n setAdjustmentNoteIdsThatAreFrozen(frozenAdjustmentNoteIds);\n setBidderFileUploadIdsThatAreFrozen(frozenBidderFileUploadContainerIds);\n\n // make sure the project info has been loaded\n const basicProjectInfo = await ProjectApi.getProjectInfoForBidPackage(selectedBidPackageId);\n setProjectInfo(basicProjectInfo);\n\n const bidPackageTotals = await BidPackageApi.getBidPackageTotals(selectedBidPackageId);\n if (bidPackageTotals) {\n bidPackagesObj.bidTotals = bidPackageTotals;\n }\n\n // Sort bidders by order\n bidPackagesObj.sortBidders();\n\n setSelectedBidPackage(bidPackagesObj);\n\n // Update staging and committed bid package refs with deep copies of the bid package object\n selectedBidPackage_Staging.current = cloneDeep(bidPackagesObj);\n selectedBidPackage_Committed.current = cloneDeep(bidPackagesObj);\n\n // Refresh the grid\n setGridRerenderTriggerObject({\n // NOTE: On the bid package page, we don't change the columns of the primary grid\n rowsChanged: true,\n primaryGridColumnsChanged: true,\n });\n\n const lineItemIdsFromBidPackage = bidPackagesObj?.lineItems.map((v) => v.id!);\n\n // Refresh the selected line items from the data we just retrieved in case line items were removed\n const newVal: Record = {\n ...selectedLineItemsMappingsCopy.current,\n };\n\n Object.keys(selectedLineItemsMappingsCopy.current).forEach((currKey) => {\n newVal[currKey] = selectedLineItemsMappingsCopy.current[currKey].filter((v) =>\n lineItemIdsFromBidPackage.includes(v),\n );\n });\n\n selectedLineItemsMappings_Change(newVal);\n\n // Refresh the bidder\n setBidderForDocumentsModal((currentBidder) => {\n if (!currentBidder) {\n return null;\n }\n return bidPackagesObj.bidders.find((b) => b.id === currentBidder!.id) || null;\n });\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('bid-package:loadBidPackagePageError'));\n history.push(ApplicationRoutes.ERROR_ERROR);\n } finally {\n hidePageLoadingOverlay();\n }\n }, [\n selectedBidPackageId,\n showPageLoadingOverlay,\n selectedLineItemsMappings_Change,\n logger,\n showErrorNotification,\n t,\n history,\n hidePageLoadingOverlay,\n ]);\n\n // Add to recent projects\n useEffect(() => {\n if (!projectId) {\n return;\n }\n\n // We aren't awaiting this because we don't care about the result\n RecentProjectsApi.addRecentProject(projectId);\n }, [projectId]);\n\n // Load bid package on selected bid package change\n useEffect(() => {\n if (selectedBidPackageId) {\n loadBidPackageDetails();\n }\n }, [loadBidPackageDetails, selectedBidPackageId]);\n\n // A ref variable to maintain the current value of the source ID's so we can tell when things changed\n const sourceIdsForChangeNotifications_CurrValue = useRef([]);\n\n // A ref variable to maintain a running list of source ID's we registered for notifications with\n const currentlyRegisteredSourceIds = useRef([]);\n\n const sourceIdsForChangeNotifications = useMemo((): string[] => {\n if (!selectedBidPackage) {\n return [];\n }\n\n const newSourceIds = (sortBy(\n [\n selectedBidPackage.id,\n selectedBidPackage.notesId,\n ...selectedBidPackage.adjustments.map((v) => v.notesId).filter((v) => v),\n ...selectedBidPackage.bidders.map((v) => v.notesId).filter((v) => v),\n ...selectedBidPackage.bidders.map((v) => v.fileUploadContainerId).filter((v) => v),\n ],\n (v) => v,\n ) as string[]).filter((v) => v);\n\n if (isEqual(newSourceIds, sourceIdsForChangeNotifications_CurrValue.current)) {\n return sourceIdsForChangeNotifications_CurrValue.current;\n }\n\n sourceIdsForChangeNotifications_CurrValue.current = newSourceIds;\n\n return newSourceIds;\n }, [selectedBidPackage]);\n\n // Listen for Signal R project events.\n // NOTE: We put SignalR callback logic in observable subscription handlers because putting it directly in the useEffect\n // where we register things with SignalR over the network causes that code to clean up and run again when any of the dependencies change,\n // which can happen a LOT and cause data loss / unnecessary network activity.\n // When this code reruns because dependencies change, it only unsubscribes / re-subscribes to an observable, which is quick and\n // doesn't involve the network.\n // C'est la React. Viva RxJS.\n useEffect(() => {\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\n const allSubscriptions = new Subscription();\n\n allSubscriptions.add(\n signalRBroadcast_Project$.subscribe(\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\n // If we receive a message during the initial data load, hold on to the message to process after\n if (!isInitialDataLoadComplete) {\n notificationsReceivedDuringInitialDataLoad.current = [\n ...notificationsReceivedDuringInitialDataLoad.current,\n { type: 'project', notification: message },\n ];\n } else {\n await projectNotificationHandler(message);\n }\n },\n ),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [projectNotificationHandler, signalRBroadcast_Project$]);\n\n // Listen for Signal R bid package events\n useEffect(() => {\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\n const allSubscriptions = new Subscription();\n\n allSubscriptions.add(\n signalRBroadcast_BidPackage$.subscribe(\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\n // If we receive a message during the initial data load, hold on to the message to process after\n if (!isInitialDataLoadComplete) {\n notificationsReceivedDuringInitialDataLoad.current = [\n ...notificationsReceivedDuringInitialDataLoad.current,\n { type: 'bid package', notification: message },\n ];\n } else {\n await bidPackageNotificationHandler(message);\n }\n },\n ),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [bidPackageNotificationHandler, signalRBroadcast_BidPackage$]);\n\n // Register for project change notifications\n useEffect(() => {\n if (!projectId) {\n return;\n }\n\n const registerForProjectChangeNotifications = async (): Promise => {\n try {\n showPageLoadingOverlay();\n\n // NOTE: the SourceId we be normalized to lowercase, when registering, so we'll need to account for that when checking it later.\n await NotificationService.registerForNotifications(projectId, (message) =>\n onSignalRBroadcast_Project(message),\n );\n logger.logDebug(`registered notification group: ${projectId}`);\n } catch {\n setLiveUpdateRegistrationFailed(true);\n } finally {\n hidePageLoadingOverlay();\n }\n };\n\n registerForProjectChangeNotifications();\n\n return () => {\n NotificationService.unregisterFromNotifications(projectId);\n logger.logDebug(`unregistered notification group: ${projectId}`);\n };\n }, [\n hidePageLoadingOverlay,\n logger,\n onSignalRBroadcast_Project,\n projectId,\n showPageLoadingOverlay,\n ]);\n\n // Register for bid package change notifications\n useEffect(() => {\n if (!selectedBidPackageId) {\n return;\n }\n\n const registerForBidPackageChangeNotifications = async (): Promise => {\n try {\n showPageLoadingOverlay();\n\n // NOTE: We have an ever-changing list of source ID's that we want to receive notifications\n // for (bid package, bid package notes, bidder notes, adjustment notes, etc.).\n // We maintain a collection of the currently subscribed source ID's, so we can tell what changed\n // when this useEffect re-runs because of dependency change(s) and not do any unnecessary\n // unregistrations / re-registrations for source ID's that didn't change.\n const sourceIdsToUnregister = currentlyRegisteredSourceIds.current.filter(\n (v) => !sourceIdsForChangeNotifications.includes(v),\n );\n\n const sourceIdsToRegister = sourceIdsForChangeNotifications.filter(\n (v) => !currentlyRegisteredSourceIds.current.includes(v),\n );\n\n // Unregister from source ID's that we no longer need\n for (const currSourceId of sourceIdsToUnregister) {\n logger.logDebug(`unregistered notification group: ${currSourceId}`);\n\n NotificationService.unregisterFromNotifications(currSourceId);\n\n // Remove the current source ID from the running list of subscriptions\n currentlyRegisteredSourceIds.current = currentlyRegisteredSourceIds.current.filter(\n (v) => v !== currSourceId,\n );\n }\n\n // Register new source ID's\n // NOTE: the SourceId we be normalized to lowercase, when registering, so we'll need to account for that when checking it later.\n await NotificationService.batchRegisterForNotifications(sourceIdsToRegister, (message) =>\n onSignalRBroadcast_BidPackage(message),\n );\n\n // Keep track of the registered sourceIds if all of them are registered successfully\n for (const currSourceId of sourceIdsToRegister) {\n logger.logDebug(`registered notification group: ${currSourceId}`);\n\n currentlyRegisteredSourceIds.current.push(currSourceId);\n }\n } catch {\n setLiveUpdateRegistrationFailed(true);\n } finally {\n hidePageLoadingOverlay();\n }\n };\n\n registerForBidPackageChangeNotifications();\n\n // NOTE: We do not return a cleanup function, we clean up SignalR subscriptions\n // in the useEffect below and at the top of this useEffect body.\n }, [\n hidePageLoadingOverlay,\n logger,\n onSignalRBroadcast_BidPackage,\n selectedBidPackageId,\n showPageLoadingOverlay,\n sourceIdsForChangeNotifications,\n ]);\n\n // When this component unmounts, unregister from things\n useEffect(() => {\n return () => {\n currentlyRegisteredSourceIds.current.forEach((currSourceId) => {\n NotificationService.unregisterFromNotifications(currSourceId);\n });\n };\n }, []);\n\n ///////////////////////////////////////////////\n\n const [gridSections, setGridSections] = useState([]);\n\n const [gridRerenderTriggerObject, setGridRerenderTriggerObject] = useState(\n {},\n );\n\n const [gridSection_Header, setGridSection_Header] = useState(null);\n\n const [\n gridSection_LineItems_Header,\n setGridSection_LineItems_Header,\n ] = useState(null);\n\n const [gridSections_LineItems, setGridSections_LineItems] = useState([]);\n\n const [\n gridSection_GeneralRequirements,\n setGridSection_GeneralRequirements,\n ] = useState(null);\n\n const [\n gridSection_TradeRequirements,\n setGridSection_TradeRequirements,\n ] = useState(null);\n\n const [\n gridSection_LineItems_Adjustments,\n setGridSection_LineItems_Adjustments,\n ] = useState(null);\n\n // NOTE: These alternates grid sections include various other grid sections that\n // visually make up an \"alternate\" section\n const [gridSections_Alternates, setGridSections_Alternates] = useState([]);\n\n const [\n gridSection_BidPackageTotals,\n setGridSection_BidPackageTotals,\n ] = useState(null);\n\n const {\n errorFunction_Adjustment,\n onBlurCallback_Adjustment,\n onChangeCallback_Adjustment,\n successFunction_Adjustment,\n } = useBidPackageBidHandler_Adjustments();\n\n const {\n onChangeCallback_LineItemBid,\n onBlurCallback_LineItemBid,\n successFunction_LineItemBid,\n errorFunction_LineItemBid,\n } = useBidPackageBidHandler_LineItemBids();\n\n const {\n onChangeCallback_LineItemRollupBid,\n onBlurCallback_LineItemRollupBid,\n successFunction_LineItemRollupBid,\n errorFunction_LineItemRollupBid,\n } = useBidPackageBidHandler_LineItemRollupBids();\n\n const {\n onChangeCallback_RequirementFulfillment,\n onBlurCallback_RequirementFulfillment,\n successFunction_RequirementFulfillment,\n errorFunction_RequirementFulfillment,\n } = useBidPackageBidHandler_RequirementFulfillments();\n\n const onBiddersSaveCallback = useCallback(\n async (functionToExecute: () => Promise) => {\n await executeCommand({\n commandToExecute: functionToExecute,\n commandExecutionType: 'relies-on-signal-r-for-completion',\n commandTimeoutFunction: loadBidPackageDetails,\n });\n },\n [executeCommand, loadBidPackageDetails],\n );\n\n const onBidPackageNotesChangeCallback = useCallback(\n async (functionToExecute: () => Promise) => {\n // NOTE: We want to wait for SignalR here\n await executeCommand({\n commandExecutionType: 'relies-on-signal-r-for-completion',\n commandToExecute: functionToExecute,\n commandSuccessCallback: (result: BidPackage | null) => {\n if (!result) {\n showErrorNotification(t('general:error'), t('bid-package:errorAddNotes'));\n return;\n }\n\n // NOTE: The function passed into this change callback function sets the notes ID on the bid package\n // so when we update the bid package here, it should register the new notes ID for updates with SignalR.\n setSelectedBidPackage(result);\n\n // Update the staging / committed bid package copies with the new data\n const stagingCopy = clone(selectedBidPackage_Staging.current)!;\n stagingCopy.notesId = result.notesId;\n stagingCopy.notes = result.notes;\n selectedBidPackage_Staging.current = stagingCopy;\n\n const committedCopy = clone(selectedBidPackage_Committed.current)!;\n committedCopy.notesId = result.notesId;\n committedCopy.notes = result.notes;\n selectedBidPackage_Committed.current = committedCopy;\n\n showSuccessNotification(t('general:success'), t('bid-package:successSetNotes'));\n },\n commandErrorCallback: (error) => {\n // NOTE: The error message will be shown for us if an actual error occurred\n logger.logError(error);\n },\n customErrorMessage: t('bid-package:errorAddNotes'),\n commandTimeoutFunction: loadBidPackageDetails,\n });\n },\n [\n executeCommand,\n loadBidPackageDetails,\n showSuccessNotification,\n t,\n showErrorNotification,\n logger,\n ],\n );\n\n const onBidderNotesChangeCallback = useCallback((bidder: Bidder) => {\n setSelectedBidPackage((currBidPackage) => {\n if (!currBidPackage) {\n return currBidPackage;\n }\n\n const matchingIndex = currBidPackage.bidders.findIndex((v) => v.id === bidder.id);\n if (matchingIndex > -1) {\n const bidPackageCopy = clone(currBidPackage);\n const biddersCopy = [...bidPackageCopy.bidders];\n biddersCopy.splice(matchingIndex, 1, bidder);\n bidPackageCopy.bidders = biddersCopy;\n\n return bidPackageCopy;\n }\n\n return currBidPackage;\n });\n }, []);\n\n const onBidderDocumentsModalClose = useCallback(() => {\n setBidderForDocumentsModal(null);\n }, []);\n\n const { addBidders, editBidder, getBiddersAddEditJSX } = useBidPackageBidders_AddEditForm(\n onBiddersSaveCallback,\n );\n\n const { editBidderNotes, getBidderNotesJSX } = useBidPackageBidders_Notes(\n onBidderNotesChangeCallback,\n );\n\n const { showBidderInfo, getBidderInfoJSX } = useBidPackageBidders_InfoModal();\n\n const {\n showBidderDocumentsModal,\n getBidderDocumentsModalJSX,\n } = useBidPackageBidders_DocumentsModal();\n\n const { getProjectInfoJSX, showProjectInfo } = useProject_Info();\n\n const {\n onChangeCallback_LineItem,\n onBlurCallback_LineItem,\n successFunction_LineItem,\n errorFunction_LineItem,\n successFunction_LineItem_Delete,\n errorFunction_LineItem_Delete,\n } = useBidPackage_LineItems();\n\n const {\n getBidPackageNotesJSX,\n successFunction_SelectedBidder,\n errorFunction_SelectedBidder,\n onLockChangeCallback,\n successFunction_Lock,\n errorFunction_Lock,\n openBidPackageNotes,\n } = useBidPackage();\n\n const { generateBidPackage_Header_GridSection } = useBidPackageGrid_Header();\n\n const { generateBidPackage_LineItems_Header_GridSection } = useBidPackageGrid_LineItems_Header();\n\n const { generateBidPackage_LineItems_GridSection } = useBidPackageGrid_LineItems();\n\n const {\n generateLineItemsAlternatesGridSectionHeaderRows,\n generateLineItemsAlternatesGridSectionHeaderRowExtensions,\n } = useBidPackageGrid_LineItems_Alternates();\n\n const { generateBidPackage_Requirements_GridSection } = useBidPackageGrid_Requirements();\n\n const { generateBidPackage_Adjustments_GridSection } = useBidPackageGrid_Adjustments();\n\n const onBidPackageLockChange = useCallback(async () => {\n if (selectedBidPackage) {\n const email = selectedBidPackage.lockedByUserEmail ? null : currentUser!.email!;\n\n const commandToProcess = onLockChangeCallback(selectedBidPackage.id, email);\n\n if (commandToProcess) {\n await executeCommand({\n commandToExecute: commandToProcess,\n commandBeforeExecutionCallback: () => {\n // Optimistically update the staging bid package so other code has up to date values to use when generating commands\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : successFunction_Lock(\n commandToProcess,\n selectedBidPackage_Staging.current,\n selectedBidPackage!,\n );\n },\n commandSuccessCallback: () => {\n // If things succeeded, update the committed bid package with the new data\n setSelectedBidPackage((bidPackage) => {\n return !bidPackage\n ? undefined\n : successFunction_Lock(\n commandToProcess,\n bidPackage,\n selectedBidPackage_Committed.current!,\n );\n });\n\n selectedBidPackage_Committed.current = !selectedBidPackage_Committed.current\n ? undefined\n : successFunction_Lock(\n commandToProcess,\n selectedBidPackage_Committed.current,\n selectedBidPackage!,\n );\n },\n commandErrorCallback: () => {\n // If things failed, we restore the current bid package from the last committed data\n setSelectedBidPackage((bidPackage) => {\n return !bidPackage\n ? undefined\n : errorFunction_Lock(\n commandToProcess,\n bidPackage,\n selectedBidPackage_Committed.current!,\n );\n });\n\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : errorFunction_Lock(\n commandToProcess,\n selectedBidPackage_Staging.current,\n selectedBidPackage_Committed.current!,\n );\n },\n commandTimeoutFunction: loadBidPackageDetails,\n });\n }\n }\n }, [\n currentUser,\n errorFunction_Lock,\n executeCommand,\n loadBidPackageDetails,\n onLockChangeCallback,\n selectedBidPackage,\n successFunction_Lock,\n ]);\n\n const onLineItemsDelete = useCallback(\n (lineItemsToDelete: LineItemValue[]) => {\n if (!lineItemsToDelete.length) {\n return;\n }\n\n showConfirmationOverlay({\n text:\n lineItemsToDelete.length > 1\n ? t('bid-package:confirmDeleteMultipleLineItems')\n : t('bid-package:confirmDeleteSingleLineItem', {\n lineItemName: lineItemsToDelete[0].description,\n }),\n buttons: [\n {\n text: t('general:yes'),\n onClick: async (): Promise => {\n hideConfirmationOverlay();\n\n const commands = lineItemsToDelete.map(\n (li) => new DeleteBidPackageLineItemCommand(selectedBidPackageId!, li.id!),\n );\n\n const functionToExecute = async (): Promise => {\n await BidPackageApi.deleteBidPackageLineItems(commands);\n };\n\n await executeCommand({\n commandToExecute: functionToExecute,\n commandExecutionType: 'relies-on-signal-r-for-completion',\n commandBeforeExecutionCallback: () => {\n // Optimistically update the bid package / staging bid package so other code has up to date values to use when generating commands\n setSelectedBidPackage((bidPackage) => {\n return !bidPackage\n ? bidPackage\n : successFunction_LineItem_Delete(commands, bidPackage);\n });\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : successFunction_LineItem_Delete(commands, selectedBidPackage_Staging.current);\n },\n commandSuccessCallback: () => {\n // The success notification for this action is handled by the subscriptions useEffect\n // If things succeeded, update the committed bid package with the new data\n selectedBidPackage_Committed.current = !selectedBidPackage_Committed.current\n ? undefined\n : successFunction_LineItem_Delete(\n commands,\n selectedBidPackage_Committed.current,\n );\n },\n commandErrorCallback: () => {\n // If things failed, we restore the current bid package from the last committed data\n setSelectedBidPackage((bidPackage) => {\n return !bidPackage\n ? undefined\n : errorFunction_LineItem_Delete(\n commands,\n bidPackage,\n selectedBidPackage_Committed.current!,\n );\n });\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : errorFunction_LineItem_Delete(\n commands,\n selectedBidPackage_Staging.current,\n selectedBidPackage_Committed.current!,\n );\n },\n commandTimeoutFunction: loadBidPackageDetails,\n customErrorMessage: t('bid-package:deleteLineItemsError'),\n });\n },\n color: 'normal',\n },\n {\n text: t('general:no'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n },\n [\n errorFunction_LineItem_Delete,\n executeCommand,\n hideConfirmationOverlay,\n loadBidPackageDetails,\n selectedBidPackageId,\n showConfirmationOverlay,\n successFunction_LineItem_Delete,\n t,\n ],\n );\n\n // Listen for grid events\n useEffect(() => {\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\n const allSubscriptions = new Subscription();\n\n // Handler for selected row\n allSubscriptions.add(\n selectedRowsChange$.subscribe((allSelectedItems: GridSectionRowMetadataMapping[]): void => {\n // NOTE: The row ID of line item details rows will be the line item ID\n const selectedLineItemIds = allSelectedItems\n .filter((v) =>\n // NOTE: We use \"starts with\" here since we can have multiple line items sections (one for each alternate)\n v.gridSectionId.startsWith(BidPackageConstants.GridSectionIds.LINE_ITEMS),\n )\n .map((v) => v.rowId);\n\n // NOTE: This does not match line items for selected grouped rows\n const selectedLineItems =\n selectedBidPackage?.lineItems?.filter((v) => selectedLineItemIds.includes(v.id!)) || [];\n\n // Group selected line items into \"sections\" (ie. main section and sections for specific alternates)\n const lineItemsGroupedByAlternateId = groupBy(\n selectedLineItems,\n (v) => v.alternateId ?? null,\n );\n\n const newVal: Record = {};\n\n Object.keys(lineItemsGroupedByAlternateId).forEach((currKey) => {\n newVal[currKey === 'null' ? '' : currKey] = lineItemsGroupedByAlternateId[currKey].map(\n (v) => v.id!,\n );\n });\n\n selectedLineItemsMappings_Change(newVal);\n }),\n );\n\n // Handler for items being reordered\n allSubscriptions.add(\n itemsReordered$.subscribe(async (newValue: BTGridItemsReorderedInfo) => {\n const { dragInfo, dropDirection, dropTarget } = newValue;\n // Bidders\n if (dragInfo.sortableContainerId === BidderGridRowSortableContainerId) {\n // Get bidder IDs\n const dropTargetBidderName = dropTarget.metadata?.bidderName;\n const draggedBidderName = dragInfo.row.metadata?.bidderName;\n if (!dropTargetBidderName || !draggedBidderName) {\n return;\n }\n\n // Get bidders\n const draggedBidder = selectedBidPackage!.bidders.find(\n (b) => b.companyName === draggedBidderName,\n );\n const dropTargetBidder = selectedBidPackage!.bidders.find(\n (b) => b.companyName === dropTargetBidderName,\n );\n if (!draggedBidder || !dropTargetBidder) {\n return;\n }\n\n // Get current order of bidders\n const currentOrder = draggedBidder.order!;\n const dropTargetOrder = dropTargetBidder.order!;\n\n // Determine new order\n let newOrder;\n if (dropDirection === 'left' && dropTargetOrder > currentOrder) {\n newOrder = dropTargetOrder - 1;\n } else if (dropDirection === 'left' && dropTargetOrder < currentOrder) {\n newOrder = dropTargetOrder;\n } else if (dropDirection === 'right' && dropTargetOrder > currentOrder) {\n newOrder = dropTargetOrder;\n } else if (dropDirection === 'right' && dropTargetOrder < currentOrder) {\n newOrder = dropTargetOrder + 1;\n } else {\n return;\n }\n\n // If current order and new order match, it's a no-op\n if (currentOrder === newOrder) {\n return;\n }\n\n // Reorder bidders\n await executeCommand({\n commandToExecute: new SetBidderOrderCommand(\n selectedBidPackage!.id,\n draggedBidderName,\n newOrder,\n ),\n commandExecutionType: 'relies-on-signal-r-for-completion',\n commandTimeoutFunction: loadBidPackageDetails,\n });\n }\n\n // Line Items\n if (dragInfo.sortableContainerId.startsWith(LineItemGridRowSortableContainerId)) {\n const classifications: string[] = [];\n const draggedRowGroupingLevel = dragInfo.row.groupingInfo?.groupingLevel ?? 0;\n const dropTargetGroupingLevel = dropTarget.groupingInfo?.groupingLevel ?? 0;\n\n if (normalizeNullOrUndefined(dragInfo.groupingKey1)) {\n classifications.push(dragInfo.groupingKey1!);\n }\n if (normalizeNullOrUndefined(dragInfo.groupingKey2)) {\n classifications.push(dragInfo.groupingKey2!);\n }\n\n // If the drag goruping level is in a higher hierarchy than the drop target,\n // it means we are trying to move the dragged element after the drop target's parent\n let targetOrder = dropTarget.groupingInfo?.order;\n if (draggedRowGroupingLevel < dropTargetGroupingLevel) {\n targetOrder =\n dragInfo.row.groupingInfo?.groupingLevel === 0\n ? dropTarget.groupingInfo?.groupingParent1Info?.order\n : dropTarget.groupingInfo?.groupingParent2Info?.order;\n }\n // If the drop target is valid and has a higher grouping level, it can only be the dragged element's immediate parent\n else if (draggedRowGroupingLevel > dropTargetGroupingLevel) {\n targetOrder = 0;\n }\n\n if (targetOrder == null) {\n return;\n }\n\n let newOrder = -1;\n const currentOrder = dragInfo.row.groupingInfo?.order ?? 0;\n if (dropDirection === 'top' && targetOrder > currentOrder) {\n newOrder = targetOrder - 1;\n } else if (dropDirection === 'top' && targetOrder < currentOrder) {\n newOrder = targetOrder;\n } else if (dropDirection === 'bottom' && targetOrder > currentOrder) {\n newOrder = targetOrder;\n } else if (dropDirection === 'bottom' && targetOrder < currentOrder) {\n newOrder = targetOrder + 1;\n } else {\n return;\n }\n\n // If current order and new order match, it's a no-op\n if (currentOrder === newOrder) {\n return;\n }\n\n const commandToExecute = dragInfo.isGroupedRow\n ? new UpdateBidPackageLineItemGroupOrderCommand(\n selectedBidPackage!.id,\n classifications,\n dragInfo.row.dataAttributes!['alternate-name'],\n newOrder,\n )\n : new UpdateBidPackageLineItemOrderCommand(\n selectedBidPackage!.id,\n dragInfo.isGroupedRow ? null : dragInfo.row.id,\n dragInfo.row.dataAttributes!['alternate-name'],\n newOrder,\n );\n\n await executeCommand({\n commandToExecute: commandToExecute,\n commandExecutionType: 'page-loading-overlay',\n commandTimeoutFunction: loadBidPackageDetails,\n });\n }\n }),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [\n executeCommand,\n itemsReordered$,\n loadBidPackageDetails,\n selectedBidPackage,\n selectedLineItemsMappings_Change,\n selectedRowsChange$,\n ]);\n\n // Listen for line item events\n useEffect(() => {\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\n const allSubscriptions = new Subscription();\n\n allSubscriptions.add(\n selectedLineItemsMappings$.subscribe((newSelectedLineItems) => {\n selectedLineItemsMappingsCopy.current = newSelectedLineItems;\n }),\n );\n\n // Line item change event\n allSubscriptions.add(\n lineItemChange$.subscribe((updatedLineItem: LineItemValue) => {\n setSelectedBidPackage((currBidPackage) => {\n return currBidPackage\n ? onChangeCallback_LineItem(currBidPackage, updatedLineItem)\n : undefined;\n });\n\n // After a certain timeout, we want to auto-save (ie. trigger the blur event with the last changed value the user provided)\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n }\n\n autoSaveTimeout.current = setTimeout(() => {\n lineItem_Blur(updatedLineItem);\n\n autoSaveTimeout.current = null;\n }, BidPackageConstants.Config.BID_PACKAGE_AUTOSAVE_TIMEOUT);\n }),\n );\n\n // Line item blur event\n allSubscriptions.add(\n lineItemBlur$.subscribe(async (updatedLineItem: LineItemValue) => {\n // If the auto save timeout is active, cancel it since it just triggers this code\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n autoSaveTimeout.current = null;\n }\n\n const commandToProcess = onBlurCallback_LineItem(\n selectedBidPackage_Staging.current!,\n selectedBidPackage!,\n updatedLineItem,\n );\n\n if (commandToProcess) {\n await executeCommand({\n commandToExecute: async () => {\n await BidPackageApi.updateBidPackageLineItems([\n commandToProcess as UpdateBidPackageLineItemCommand,\n ]);\n },\n commandBeforeExecutionCallback: () => {\n // Optimistically update the staging bid package so other code has up to date values to use when generating commands\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : successFunction_LineItem(\n commandToProcess,\n selectedBidPackage_Staging.current,\n selectedBidPackage!,\n );\n },\n commandSuccessCallback: () => {\n // If things succeeded, update the committed bid package with the new data\n selectedBidPackage_Committed.current = !selectedBidPackage_Committed.current\n ? undefined\n : successFunction_LineItem(\n commandToProcess,\n selectedBidPackage_Committed.current,\n selectedBidPackage!,\n );\n },\n commandErrorCallback: () => {\n // If things failed, we restore the current bid package from the last committed data\n setSelectedBidPackage((bidPackage) => {\n return !bidPackage\n ? undefined\n : errorFunction_LineItem(\n commandToProcess,\n bidPackage,\n selectedBidPackage_Committed.current!,\n );\n });\n\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : errorFunction_LineItem(\n commandToProcess,\n selectedBidPackage_Staging.current,\n selectedBidPackage_Committed.current!,\n );\n },\n commandTimeoutFunction: loadBidPackageDetails,\n });\n }\n }),\n );\n\n // Single line items add event\n allSubscriptions.add(\n lineItemsAdd$.subscribe((alternateName: string | null) => {\n setAlternateToAddLineItemsTo(alternateName);\n setLineItemsModalState({ isOpen: true, mode: 'add' });\n }),\n );\n\n // Line item(s) edit event\n allSubscriptions.add(\n lineItemEdit$.subscribe((idOfLineItemToEdit: string) => {\n // Get the line item\n const lineItem = selectedBidPackage?.lineItems.find((v) => v.id === idOfLineItemToEdit);\n\n if (lineItem) {\n setLineItemsToEdit([lineItem]);\n\n setLineItemsModalState({ isOpen: true, mode: 'edit' });\n } else {\n logger.logError(`Unable to find line item (to edit) with id '${idOfLineItemToEdit}'.`);\n }\n }),\n );\n\n // Editing multiple line items\n allSubscriptions.add(\n lineItemsEdit$.subscribe((alternateId: string | null) => {\n const idsOfLineItemsToEdit = selectedLineItemsMappingsCopy.current[alternateId ?? ''] || [];\n if (idsOfLineItemsToEdit.length) {\n // Get the line items\n const lineItemsToEdit = selectedBidPackage?.lineItems.filter((v) =>\n idsOfLineItemsToEdit.includes(v.id!),\n );\n\n if (lineItemsToEdit) {\n // Sort the line items by description because they could have been added to the collection any which way\n setLineItemsToEdit(sortBy(lineItemsToEdit, (v) => v.description));\n\n setLineItemsModalState({ isOpen: true, mode: 'edit' });\n } else {\n logger.logError(`Unable to find line items (to edit) with the supplied ids.`);\n }\n }\n }),\n );\n\n // Single line item delete event\n allSubscriptions.add(\n lineItemDelete$.subscribe(async (idOfLineItemToDelete: string) => {\n // Get the line item\n const lineItem = selectedBidPackage?.lineItems.find((v) => v.id === idOfLineItemToDelete);\n\n if (lineItem) {\n await onLineItemsDelete([lineItem]);\n } else {\n logger.logError(\n `Unable to find line item (to delete) with id '${idOfLineItemToDelete}'.`,\n );\n }\n }),\n );\n\n // Deleting multiple line items\n allSubscriptions.add(\n lineItemsDelete$.subscribe(async (alternateId: string | null) => {\n const idsOfLineItemsToDelete =\n selectedLineItemsMappingsCopy.current[alternateId ?? ''] || [];\n if (idsOfLineItemsToDelete.length) {\n // Get the line items\n const lineItemsToDelete = selectedBidPackage?.lineItems.filter((v) =>\n idsOfLineItemsToDelete.includes(v.id!),\n );\n\n if (lineItemsToDelete) {\n await onLineItemsDelete(lineItemsToDelete);\n } else {\n logger.logError(`Unable to find line items (to delete) with the supplied ids.`);\n }\n }\n }),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [\n errorFunction_LineItem,\n errorFunction_LineItem_Delete,\n executeCommand,\n hideConfirmationOverlay,\n lineItemBlur$,\n lineItemChange$,\n lineItem_Blur,\n lineItemsAdd$,\n lineItemsDelete$,\n lineItemsEdit$,\n loadBidPackageDetails,\n onBlurCallback_LineItem,\n onChangeCallback_LineItem,\n selectedBidPackage,\n showConfirmationOverlay,\n showSuccessNotification,\n successFunction_LineItem,\n successFunction_LineItem_Delete,\n t,\n lineItemEdit$,\n lineItemsToEdit,\n lineItemDelete$,\n onLineItemsDelete,\n selectedLineItemsMappings$,\n logger,\n ]);\n\n // Listen for line item bid events\n useEffect(() => {\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\n const allSubscriptions = new Subscription();\n\n // Line item bid change event\n allSubscriptions.add(\n lineItemBidChange$.subscribe((bidValue: LineItemBidValue) => {\n setSelectedBidPackage((currBidPackage) => {\n return currBidPackage\n ? onChangeCallback_LineItemBid(currBidPackage, bidValue)\n : undefined;\n });\n\n // After a certain timeout, we want to auto-save (ie. trigger the blur event with the last changed value the user provided)\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n }\n\n autoSaveTimeout.current = setTimeout(() => {\n lineItemBid_Blur(bidValue);\n\n autoSaveTimeout.current = null;\n }, BidPackageConstants.Config.BID_PACKAGE_AUTOSAVE_TIMEOUT);\n }),\n );\n\n // Line item bid blur event\n allSubscriptions.add(\n lineItemBidBlur$.subscribe(async (bidValue: LineItemBidValue) => {\n // If the auto save timeout is active, cancel it since it just triggers this code\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n autoSaveTimeout.current = null;\n }\n\n // NOTE: A \"bid\" is made up of 2 input fields - a numeric input field and a select input.\n // We want to send a command to the server when a bid changes, but only when the user truly leaves the 2 input fields,\n // and isn't just navigating between them for the same bid.\n // We do this by putting the blur callback code on the JavaScript scheduler with a setTimeout and a delay of 0.\n // If the user leaves one bid input and focuses on another input for the same bid, a blur event will fire, followed immediately\n // by a focus event. By putting this callback logic on a timeout, we can delay its execution until after the blur / focus events process.\n // In the focus event, we can check if the newly focused input is for the same bid as the last focused one and cancel\n // the blur logic timeout altogether.\n lineItemBlurTimeout.current = setTimeout(async () => {\n // Reset the blur timeout\n lineItemBlurTimeout.current = null;\n\n const updateIsDirtyFlag = (bidPackageToUpdate: BidPackage): BidPackage => {\n const copy = clone(bidPackageToUpdate);\n const lineItem = copy.getLineItemById(bidValue.bidPackageLineItemId!);\n\n if (lineItem) {\n const indexOfLineItemBid = lineItem.bids.findIndex(\n (v) =>\n normalizeNullOrUndefined(v.bidderId) ===\n normalizeNullOrUndefined(bidValue.bidderId!),\n );\n\n if (indexOfLineItemBid > -1) {\n const bidsCopy = [...lineItem.bids];\n\n const newObj = clone(bidsCopy[indexOfLineItemBid]);\n newObj.isDirty = false;\n\n bidsCopy[indexOfLineItemBid] = newObj;\n lineItem.bids = bidsCopy;\n }\n }\n\n return copy;\n };\n\n // Find the current bid and reset the isDirty flag to false since we're \"committing\" the data in this function\n // by generating a command and sending it to the server\n setSelectedBidPackage((currBidPackage) => {\n if (!currBidPackage) {\n return currBidPackage;\n }\n\n return updateIsDirtyFlag(currBidPackage);\n });\n\n // Update the staging and committed copies in case they also had the \"isDirty\" flag set\n selectedBidPackage_Staging.current = updateIsDirtyFlag(\n selectedBidPackage_Staging.current!,\n );\n\n selectedBidPackage_Committed.current = updateIsDirtyFlag(\n selectedBidPackage_Committed.current!,\n );\n\n const commandToProcess = onBlurCallback_LineItemBid(\n selectedBidPackage_Staging.current!,\n selectedBidPackage!,\n bidValue,\n );\n\n if (commandToProcess) {\n await executeCommand({\n commandToExecute: commandToProcess,\n commandBeforeExecutionCallback: () => {\n // Optimistically update the staging bid package so other code has up to date values to use when generating commands\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : successFunction_LineItemBid(\n commandToProcess,\n selectedBidPackage_Staging.current,\n selectedBidPackage!,\n );\n },\n commandSuccessCallback: () => {\n // If things succeeded, update the committed bid package with the new data\n selectedBidPackage_Committed.current = !selectedBidPackage_Committed.current\n ? undefined\n : successFunction_LineItemBid(\n commandToProcess,\n selectedBidPackage_Committed.current,\n selectedBidPackage!,\n );\n },\n commandErrorCallback: () => {\n // If things failed, we restore the current bid package from the last committed data\n setSelectedBidPackage((bidPackage) => {\n return !bidPackage\n ? bidPackage\n : errorFunction_LineItemBid(\n commandToProcess,\n bidPackage,\n selectedBidPackage_Committed.current!,\n );\n });\n\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : errorFunction_LineItemBid(\n commandToProcess,\n selectedBidPackage_Staging.current,\n selectedBidPackage_Committed.current!,\n );\n },\n commandTimeoutFunction: loadBidPackageDetails,\n });\n }\n\n // If we didn't generate a command or we generated a delete command, check to see if the current bid value is valid and if it isn't,\n // delete it from the collection.\n // Since we now don't fire the blur logic until the user truly leaves both bid inputs, we can now clean up after ourselves better\n // and not leave partial invalid bids around.\n if (\n commandToProcess instanceof DeleteLineItemBidOnBidPackageCommand ||\n (!commandToProcess &&\n !BidPackageLineItemBid.isBidValid(bidValue.price, bidValue.classification))\n ) {\n setSelectedBidPackage((bidPackage) => {\n if (!bidPackage) {\n return bidPackage;\n }\n\n const copy = clone(bidPackage);\n copy.deleteLineItemBid(bidValue.bidPackageLineItemId!, bidValue.bidderId!, false);\n return copy;\n });\n }\n }, 0);\n }),\n );\n\n allSubscriptions.add(\n lineItemBidFocus$.subscribe((bidInfo) => {\n // If there is a blur timeout active, check the line item bid info to see if it matches what triggered\n // the focus event (meaning we navigated between the numeric input / select inputs for the same line item bid).\n // If this is the case, prevent the blur event from firing until we navigate away from both of the input fields\n // that make up a \"bid field\".\n if (lineItemBlurTimeout.current && lastFocusedLineItemBidInfo.current) {\n if (\n lastFocusedLineItemBidInfo.current.bidPackageLineItemId ===\n bidInfo.bidPackageLineItemId &&\n lastFocusedLineItemBidInfo.current.bidderId === bidInfo.bidderId\n ) {\n clearTimeout(lineItemBlurTimeout.current);\n lineItemBlurTimeout.current = null;\n }\n }\n\n lastFocusedLineItemBidInfo.current = {\n ...bidInfo,\n };\n }),\n );\n\n // Line item rollup bid change event\n allSubscriptions.add(\n lineItemRollupBidChange$.subscribe((bidValue: LineItemRollupBidValue) => {\n setSelectedBidPackage((currBidPackage) => {\n return currBidPackage\n ? onChangeCallback_LineItemRollupBid(currBidPackage, bidValue)\n : undefined;\n });\n\n // After a certain timeout, we want to auto-save (ie. trigger the blur event with the last changed value the user provided)\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n }\n\n autoSaveTimeout.current = setTimeout(() => {\n lineItemRollupBid_Blur(bidValue);\n\n autoSaveTimeout.current = null;\n }, BidPackageConstants.Config.BID_PACKAGE_AUTOSAVE_TIMEOUT);\n }),\n );\n\n // Line item rollup bid blur event\n allSubscriptions.add(\n lineItemRollupBidBlur$.subscribe(async (bidValue: LineItemRollupBidValue) => {\n // If the auto save timeout is active, cancel it since it just triggers this code\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n autoSaveTimeout.current = null;\n }\n\n const updateIsDirtyFlag = (bidPackageToUpdate: BidPackage): BidPackage => {\n const copy = clone(bidPackageToUpdate);\n\n const indexOfRollupBid = copy.lineItemRollupBids.findIndex(\n (v) =>\n normalizeNullOrUndefined(v.alternateId) ===\n normalizeNullOrUndefined(bidValue.alternateId) &&\n normalizeNullOrUndefined(v.bidderId) ===\n normalizeNullOrUndefined(bidValue.bidderId) &&\n normalizeNullOrUndefined(v.metadataValue1) ===\n normalizeNullOrUndefined(bidValue.lineItemRollup1) &&\n normalizeNullOrUndefined(v.metadataValue2) ===\n normalizeNullOrUndefined(bidValue.lineItemRollup2),\n );\n\n if (indexOfRollupBid > -1) {\n const rollupBidsCopy = [...copy.lineItemRollupBids];\n\n const newObj = clone(rollupBidsCopy[indexOfRollupBid]);\n newObj.isDirty = false;\n\n rollupBidsCopy[indexOfRollupBid] = newObj;\n copy.lineItemRollupBids = rollupBidsCopy;\n }\n\n return copy;\n };\n\n // Find the current adjustment and reset the isDirty flag to false since we're \"committing\" the data in this function\n // by generating a command and sending it to the server\n setSelectedBidPackage((currBidPackage) => {\n if (!currBidPackage) {\n return currBidPackage;\n }\n\n return updateIsDirtyFlag(currBidPackage);\n });\n\n // Update the staging and committed copies in case they also had the \"isDirty\" flag set\n selectedBidPackage_Staging.current = updateIsDirtyFlag(selectedBidPackage_Staging.current!);\n\n selectedBidPackage_Committed.current = updateIsDirtyFlag(\n selectedBidPackage_Committed.current!,\n );\n\n const commandToProcess = onBlurCallback_LineItemRollupBid(\n selectedBidPackage_Staging.current!,\n selectedBidPackage!,\n projectInfo!.alternates,\n bidValue,\n );\n\n if (commandToProcess) {\n await executeCommand({\n commandToExecute: commandToProcess,\n commandBeforeExecutionCallback: () => {\n // Optimistically update the staging bid package so other code has up to date values to use when generating commands\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : successFunction_LineItemRollupBid(\n commandToProcess,\n projectInfo!.alternates,\n selectedBidPackage_Staging.current,\n selectedBidPackage_Committed.current!,\n );\n },\n commandSuccessCallback: () => {\n // If things succeeded, update the committed bid package with the new data\n selectedBidPackage_Committed.current = !selectedBidPackage_Committed.current\n ? undefined\n : successFunction_LineItemRollupBid(\n commandToProcess,\n projectInfo!.alternates,\n selectedBidPackage_Committed.current,\n selectedBidPackage!,\n );\n },\n commandErrorCallback: () => {\n // If things failed, we restore the current bid package from the last committed data\n setSelectedBidPackage((bidPackage) => {\n return !bidPackage\n ? bidPackage\n : errorFunction_LineItemRollupBid(\n commandToProcess,\n projectInfo!.alternates,\n bidPackage,\n selectedBidPackage_Committed.current!,\n );\n });\n\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : errorFunction_LineItemRollupBid(\n commandToProcess,\n projectInfo!.alternates,\n selectedBidPackage_Staging.current,\n selectedBidPackage_Committed.current!,\n );\n },\n commandTimeoutFunction: loadBidPackageDetails,\n });\n }\n }),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [\n errorFunction_LineItemBid,\n errorFunction_LineItemRollupBid,\n executeCommand,\n lineItemBidBlur$,\n lineItemBidChange$,\n lineItemBidFocus$,\n lineItemBid_Blur,\n lineItemRollupBidBlur$,\n lineItemRollupBidChange$,\n lineItemRollupBid_Blur,\n loadBidPackageDetails,\n onBlurCallback_LineItemBid,\n onBlurCallback_LineItemRollupBid,\n onChangeCallback_LineItemBid,\n onChangeCallback_LineItemRollupBid,\n projectInfo,\n selectedBidPackage,\n successFunction_LineItemBid,\n successFunction_LineItemRollupBid,\n ]);\n\n // Listen for adjustments events\n useEffect(() => {\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\n const allSubscriptions = new Subscription();\n\n // Adjustment change event\n allSubscriptions.add(\n adjustmentChange$.subscribe((bidValue: AdjustmentBidValue) => {\n setSelectedBidPackage((currBidPackage) => {\n return currBidPackage ? onChangeCallback_Adjustment(currBidPackage, bidValue) : undefined;\n });\n\n // After a certain timeout, we want to auto-save (ie. trigger the blur event with the last changed value the user provided)\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n }\n\n autoSaveTimeout.current = setTimeout(() => {\n adjustment_Blur(bidValue);\n\n autoSaveTimeout.current = null;\n }, BidPackageConstants.Config.BID_PACKAGE_AUTOSAVE_TIMEOUT);\n }),\n );\n\n // Adjustment blur event\n allSubscriptions.add(\n adjustmentBlur$.subscribe(async (bidValue: AdjustmentBidValue) => {\n // If the auto save timeout is active, cancel it since it just triggers this code\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n autoSaveTimeout.current = null;\n }\n\n const updateIsDirtyFlag = (bidPackageToUpdate: BidPackage): BidPackage => {\n const copy = clone(bidPackageToUpdate);\n\n const indexOfAdjustment = copy.adjustments.findIndex(\n (v) =>\n normalizeNullOrUndefined(v.alternateId) ===\n normalizeNullOrUndefined(bidValue.alternateId) &&\n normalizeNullOrUndefined(v.bidderId) ===\n normalizeNullOrUndefined(bidValue.bidderId),\n );\n\n if (indexOfAdjustment > -1) {\n const adjustmentsCopy = [...copy.adjustments];\n\n const newObj = clone(adjustmentsCopy[indexOfAdjustment]);\n newObj.isDirty = false;\n\n adjustmentsCopy[indexOfAdjustment] = newObj;\n copy.adjustments = adjustmentsCopy;\n }\n\n return copy;\n };\n\n // Find the current adjustment and reset the isDirty flag to false since we're \"committing\" the data in this function\n // by generating a command and sending it to the server\n setSelectedBidPackage((currBidPackage) => {\n if (!currBidPackage) {\n return currBidPackage;\n }\n\n return updateIsDirtyFlag(currBidPackage);\n });\n\n // Update the staging and committed copies in case they also had the \"isDirty\" flag set\n selectedBidPackage_Staging.current = updateIsDirtyFlag(selectedBidPackage_Staging.current!);\n\n selectedBidPackage_Committed.current = updateIsDirtyFlag(\n selectedBidPackage_Committed.current!,\n );\n\n const commandToProcess = onBlurCallback_Adjustment(\n selectedBidPackage_Staging.current!,\n selectedBidPackage!,\n projectInfo!.alternates,\n bidValue,\n );\n\n if (commandToProcess) {\n await executeCommand({\n commandToExecute: commandToProcess,\n commandBeforeExecutionCallback: () => {\n // Optimistically update the staging bid package so other code has up to date values to use when generating commands\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : successFunction_Adjustment(\n commandToProcess,\n projectInfo!.alternates,\n selectedBidPackage_Staging.current,\n selectedBidPackage!,\n );\n },\n commandSuccessCallback: () => {\n // If things succeeded, update the committed bid package with the new data\n selectedBidPackage_Committed.current = !selectedBidPackage_Committed.current\n ? undefined\n : successFunction_Adjustment(\n commandToProcess,\n projectInfo!.alternates,\n selectedBidPackage_Committed.current,\n selectedBidPackage!,\n );\n },\n commandErrorCallback: () => {\n // If things failed, we restore the current bid package from the last committed data\n setSelectedBidPackage((bidPackage) => {\n return !bidPackage\n ? undefined\n : errorFunction_Adjustment(\n commandToProcess,\n projectInfo!.alternates,\n bidPackage,\n selectedBidPackage_Committed.current!,\n );\n });\n\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : errorFunction_Adjustment(\n commandToProcess,\n projectInfo!.alternates,\n selectedBidPackage_Staging.current,\n selectedBidPackage_Committed.current!,\n );\n },\n commandTimeoutFunction: loadBidPackageDetails,\n });\n }\n }),\n );\n\n // Open adjustment notes\n allSubscriptions.add(\n adjustmentNotesOpen$.subscribe(\n (\n adjustmentData: {\n alternateId: string | null;\n bidderId: string;\n } | null,\n ) => {\n let matchingAdjustment = selectedBidPackage?.adjustments.find(\n (v) =>\n normalizeNullOrUndefined(v.alternateId) ===\n normalizeNullOrUndefined(adjustmentData?.alternateId) &&\n normalizeNullOrUndefined(v.bidderId) ===\n normalizeNullOrUndefined(adjustmentData?.bidderId),\n );\n\n // If we don't already have an adjustment to tie the notes to, we can create one on the client-side for now,\n // and one will get created on the server when the \"add notes\" command gets sent\n if (!matchingAdjustment) {\n matchingAdjustment = new Adjustment({\n alternateId: adjustmentData!.alternateId ?? undefined,\n bidPackageId: selectedBidPackage!.id,\n bidderId: adjustmentData!.bidderId,\n id: generateUuid(),\n value: null,\n notesId: undefined,\n });\n\n const copy = clone(selectedBidPackage!);\n copy.adjustments = [...copy.adjustments, matchingAdjustment!];\n setSelectedBidPackage(copy);\n\n const copy_Staging = cloneDeep(selectedBidPackage_Staging.current!);\n copy_Staging.adjustments = [\n ...copy_Staging.adjustments,\n cloneDeep(matchingAdjustment!),\n ];\n\n const copy_Committed = cloneDeep(selectedBidPackage_Committed.current!);\n copy_Committed.adjustments = [\n ...copy_Committed.adjustments,\n cloneDeep(matchingAdjustment!),\n ];\n }\n\n setLastEditedAdjustmentForAdjustmentNotes(matchingAdjustment);\n editAdjustmentNotes(matchingAdjustment);\n },\n ),\n );\n\n // Adjustment notes saved\n allSubscriptions.add(\n adjustmentNotesSave$.subscribe((adjustment: Adjustment) => {\n setSelectedBidPackage((currBidPackage) => {\n if (!currBidPackage) {\n return currBidPackage;\n }\n\n const matchingIndex = currBidPackage.adjustments.findIndex((v) => v.id === adjustment.id);\n\n if (matchingIndex > -1) {\n const bidPackageCopy = clone(currBidPackage);\n const adjustmentsCopy = [...bidPackageCopy.adjustments];\n adjustmentsCopy.splice(matchingIndex, 1, adjustment);\n bidPackageCopy.adjustments = adjustmentsCopy;\n return bidPackageCopy;\n }\n\n return currBidPackage;\n });\n\n // NOTE: The change notifications code will run and update the staging and committed copies of the bid package notes.\n // There is no need to update them here because we don't use those in any comparison logic when saving notes like\n // we do with line items, bids, etc.\n }),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [\n adjustmentBlur$,\n adjustmentChange$,\n adjustmentNotesOpen$,\n adjustmentNotesSave$,\n adjustment_Blur,\n adjustment_Change,\n editAdjustmentNotes,\n errorFunction_Adjustment,\n executeCommand,\n loadBidPackageDetails,\n onBlurCallback_Adjustment,\n onChangeCallback_Adjustment,\n projectInfo,\n selectedBidPackage,\n successFunction_Adjustment,\n ]);\n\n // Listen for requirement fulfillment events\n useEffect(() => {\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\n const allSubscriptions = new Subscription();\n\n allSubscriptions.add(\n requirementFulfillmentFocus$.subscribe((bidInfo) => {\n // If there is a blur timeout active, check the requirement fulfillment bid info to see if it matches what triggered\n // the focus event (meaning we navigated between the numeric input / select inputs for the same line item bid).\n // If this is the case, prevent the blur event from firing until we navigate away from both of the input fields\n // that make up a \"bid field\".\n\n if (\n requirementFulfillmentBlurTimeout.current &&\n lastFocusedRequirementFulfillmentBidInfo.current\n ) {\n if (\n lastFocusedRequirementFulfillmentBidInfo.current.requirementId ===\n bidInfo.requirementId &&\n lastFocusedRequirementFulfillmentBidInfo.current.bidderId === bidInfo.bidderId\n ) {\n clearTimeout(requirementFulfillmentBlurTimeout.current);\n requirementFulfillmentBlurTimeout.current = null;\n }\n }\n\n lastFocusedRequirementFulfillmentBidInfo.current = {\n requirementId: bidInfo.requirementId,\n bidderId: bidInfo.bidderId,\n };\n }),\n );\n\n // Requirement fulfillment change event\n allSubscriptions.add(\n requirementFulfillmentChange$.subscribe((bidValue: RequirementFulfillmentBidValue) => {\n setSelectedBidPackage((currBidPackage) => {\n return currBidPackage\n ? onChangeCallback_RequirementFulfillment(currBidPackage, bidValue)\n : undefined;\n });\n\n // After a certain timeout, we want to auto-save (ie. trigger the blur event with the last changed value the user provided)\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n }\n\n autoSaveTimeout.current = setTimeout(() => {\n requirementFulfillment_Blur(bidValue);\n\n autoSaveTimeout.current = null;\n }, BidPackageConstants.Config.BID_PACKAGE_AUTOSAVE_TIMEOUT);\n }),\n );\n\n // Requirement fulfillment blur event\n allSubscriptions.add(\n requirementFulfillmentBlur$.subscribe(async (bidValue: RequirementFulfillmentBidValue) => {\n // If the auto save timeout is active, cancel it since it just triggers this code\n if (autoSaveTimeout.current) {\n clearTimeout(autoSaveTimeout.current);\n autoSaveTimeout.current = null;\n }\n\n // NOTE: A \"bid\" is made up of 2 input fields - a numeric input field and a select input.\n // We want to send a command to the server when a bid changes, but only when the user truly leaves the 2 input fields,\n // and isn't just navigating between them for the same bid.\n // We do this by putting the blur callback code on the JavaScript scheduler with a setTimeout and a delay of 0.\n // If the user leaves one bid input and focuses on another input for the same bid, a blur event will fire, followed immediately\n // by a focus event. By putting this callback logic on a timeout, we can delay its execution until after the blur / focus events process.\n // In the focus event, we can check if the newly focused input is for the same bid as the last focused one and cancel\n // the blur logic timeout altogether.\n requirementFulfillmentBlurTimeout.current = setTimeout(async () => {\n // Reset the blur timeout\n requirementFulfillmentBlurTimeout.current = null;\n\n const updateIsDirtyFlag = (bidPackageToUpdate: BidPackage): BidPackage => {\n const copy = clone(bidPackageToUpdate);\n\n const requirement = copy.getRequirement(bidValue.requirementId!);\n const requirementFulfillment = copy.getRequirementFulfillment(\n bidValue.requirementId!,\n bidValue.bidderId!,\n );\n\n if (requirement && requirementFulfillment) {\n const indexOfFulfillment = requirement.requirementFulfillments.findIndex(\n (v) =>\n normalizeNullOrUndefined(v.bidderId) ===\n normalizeNullOrUndefined(bidValue.bidderId!),\n );\n\n if (indexOfFulfillment > -1) {\n const fulfillmentsCopy = [...requirement!.requirementFulfillments];\n\n const newObj = clone(fulfillmentsCopy[indexOfFulfillment]);\n newObj.isDirty = false;\n\n fulfillmentsCopy[indexOfFulfillment] = newObj;\n requirement.requirementFulfillments = fulfillmentsCopy;\n }\n }\n\n return copy;\n };\n\n // Find the current bid and reset the isDirty flag to false since we're \"committing\" the data in this function\n // by generating a command and sending it to the server\n setSelectedBidPackage((currBidPackage) => {\n if (!currBidPackage) {\n return currBidPackage;\n }\n\n return updateIsDirtyFlag(currBidPackage);\n });\n\n // Update the staging and committed copies in case they also had the \"isDirty\" flag set\n selectedBidPackage_Staging.current = updateIsDirtyFlag(\n selectedBidPackage_Staging.current!,\n );\n\n selectedBidPackage_Committed.current = updateIsDirtyFlag(\n selectedBidPackage_Committed.current!,\n );\n\n const commandToProcess = onBlurCallback_RequirementFulfillment(\n selectedBidPackage_Staging.current!,\n selectedBidPackage!,\n bidValue,\n );\n\n if (commandToProcess) {\n await executeCommand({\n commandToExecute: commandToProcess,\n commandBeforeExecutionCallback: () => {\n // Optimistically update the staging bid package so other code has up to date values to use when generating commands\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : successFunction_RequirementFulfillment(\n commandToProcess,\n selectedBidPackage_Staging.current,\n selectedBidPackage!,\n );\n },\n commandSuccessCallback: () => {\n // If things succeeded, update the committed bid package with the new data\n selectedBidPackage_Committed.current = !selectedBidPackage_Committed.current\n ? undefined\n : successFunction_RequirementFulfillment(\n commandToProcess,\n selectedBidPackage_Committed.current,\n selectedBidPackage!,\n );\n },\n commandErrorCallback: () => {\n // If things failed, we restore the current bid package from the last committed data\n setSelectedBidPackage((bidPackage) => {\n return !bidPackage\n ? undefined\n : errorFunction_RequirementFulfillment(\n commandToProcess,\n bidPackage,\n selectedBidPackage_Committed.current!,\n );\n });\n\n selectedBidPackage_Staging.current = !selectedBidPackage_Staging.current\n ? undefined\n : errorFunction_RequirementFulfillment(\n commandToProcess,\n selectedBidPackage_Staging.current,\n selectedBidPackage_Committed.current!,\n );\n },\n commandTimeoutFunction: loadBidPackageDetails,\n });\n }\n\n // If we didn't generate a command or we generated a delete command, check to see if the current bid value is valid and if it isn't,\n // delete it from the collection.\n // Since we now don't fire the blur logic until the user truly leaves both bid inputs, we can now clean up after ourselves better\n // and not leave partial invalid bids around.\n const matchingRequirement = selectedBidPackage!.requirements.find(\n (v) => v.id === bidValue.requirementId,\n )!;\n\n if (\n commandToProcess instanceof DeleteBidderRequirementFulfillmentOnBidPackageCommand ||\n (!commandToProcess &&\n matchingRequirement.requirementFulfillmentType ===\n RequirementFulfillmentTypes.Quantitative &&\n !BidPackageRequirementFulfillment.isBidValid(bidValue.price, bidValue.classification))\n ) {\n setSelectedBidPackage((bidPackage) => {\n if (!bidPackage) {\n return bidPackage;\n }\n\n const copy = clone(bidPackage);\n copy.deleteRequirementFulfillment(bidValue.requirementId!, bidValue.bidderId!, false);\n return copy;\n });\n }\n }, 0);\n }),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [\n errorFunction_RequirementFulfillment,\n executeCommand,\n loadBidPackageDetails,\n onBlurCallback_RequirementFulfillment,\n onChangeCallback_RequirementFulfillment,\n requirementFulfillmentBlur$,\n requirementFulfillmentChange$,\n requirementFulfillmentFocus$,\n requirementFulfillment_Blur,\n selectedBidPackage,\n successFunction_RequirementFulfillment,\n ]);\n\n // Listen for bidder events\n useEffect(() => {\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\n const allSubscriptions = new Subscription();\n\n // Bidder delete event\n allSubscriptions.add(\n bidderDelete$.subscribe((bidder: Bidder) => {\n showConfirmationOverlay({\n text: t('bid-package:confirmDeleteBidder', { companyName: bidder.companyName }),\n buttons: [\n {\n text: t('general:yes'),\n onClick: async (): Promise => {\n hideConfirmationOverlay();\n\n await executeCommand({\n commandToExecute: new DeleteBidPackageBidderCommand(\n selectedBidPackage!.id,\n bidder.companyName!,\n ),\n commandExecutionType: 'relies-on-signal-r-for-completion',\n commandTimeoutFunction: loadBidPackageDetails,\n });\n },\n color: 'normal',\n },\n {\n text: t('general:no'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n }),\n );\n\n // Bidder edit event\n allSubscriptions.add(bidderEdit$.subscribe(editBidder));\n\n // Bidder select event\n allSubscriptions.add(\n bidderSelect$.subscribe(\n async (newSelectedBidderId: string | null): Promise => {\n const updateSelectedBidder = async (): Promise => {\n hideConfirmationOverlay();\n\n let commandToProcess: ICommand;\n\n if (newSelectedBidderId) {\n commandToProcess = new SetSelectedBidderOnBidPackage(\n selectedBidPackage!.id,\n selectedBidPackage?.getBidder(newSelectedBidderId)?.companyName || '',\n );\n } else {\n commandToProcess = new ClearSelectedBidderOnBidPackage(selectedBidPackage!.id);\n }\n\n await executeCommand({\n commandToExecute: commandToProcess,\n commandExecutionType: 'relies-on-signal-r-for-completion',\n commandTimeoutFunction: loadBidPackageDetails,\n });\n };\n\n if (newSelectedBidderId !== selectedBidPackage?.selectedBidderId) {\n if (\n newSelectedBidderId &&\n selectedBidPackage?.doUnleveledBidsExistForBidder(newSelectedBidderId)\n ) {\n const bidderName = selectedBidPackage.bidders.find(\n (v) => v.id === newSelectedBidderId,\n )!.companyName;\n\n showConfirmationOverlay({\n text: t('bid-package:confirmationMessageChangeSelectedBidderUnleveledBids', {\n bidderName,\n }),\n buttons: [\n {\n text: t('general:select'),\n onClick: async (): Promise => {\n await updateSelectedBidder();\n },\n color: 'normal',\n },\n {\n text: t('general:dontSelect'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n } else {\n await updateSelectedBidder();\n }\n }\n },\n ),\n );\n\n // Bidders add event\n allSubscriptions.add(biddersAdd$.subscribe(addBidders));\n\n // Bidder edit notes event\n allSubscriptions.add(\n bidderEditNotes$.subscribe((bidder: Bidder) => {\n setLastEditedBidderForBidderNotes(bidder);\n editBidderNotes(bidder);\n }),\n );\n\n // Bidder edit documents event\n allSubscriptions.add(\n bidderEditDocuments$.subscribe((bidder: Bidder) => {\n setBidderForDocumentsModal(bidder);\n\n showBidderDocumentsModal();\n }),\n );\n\n // Bidder show info event\n allSubscriptions.add(\n bidderShowInfo$.subscribe((bidder: Bidder) => {\n showBidderInfo(bidder);\n }),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [\n addBidders,\n bidderDelete$,\n bidderEdit$,\n bidderEditDocuments$,\n bidderEditNotes$,\n bidderSelect$,\n bidderShowInfo$,\n biddersAdd$,\n editBidder,\n editBidderNotes,\n errorFunction_SelectedBidder,\n executeCommand,\n featureIsEnabled,\n hideConfirmationOverlay,\n lineItemChange$,\n loadBidPackageDetails,\n onChangeCallback_LineItem,\n selectedBidPackage,\n showBidderDocumentsModal,\n showBidderInfo,\n showConfirmationOverlay,\n successFunction_SelectedBidder,\n t,\n ]);\n\n // Listen for other events\n useEffect(() => {\n const allSubscriptions = new Subscription();\n\n allSubscriptions.add(\n keyboardShortcutsInfoIsOpen$.subscribe((v) => {\n setKeyboardShortcutsInfoIsOpen(v);\n }),\n );\n\n allSubscriptions.add(\n lockBidPackage$.subscribe((v) => {\n onBidPackageLockChange();\n }),\n );\n\n allSubscriptions.add(\n bidPackageNotes$.subscribe((newValue) => {\n openBidPackageNotes(newValue);\n }),\n );\n\n allSubscriptions.add(\n viewProjectInfo$.subscribe(async () => {\n if (!projectDetailInfo) {\n showPageLoadingOverlay();\n\n const info = await loadProjectDetailInfo();\n\n hidePageLoadingOverlay();\n\n showProjectInfo(info!);\n } else {\n showProjectInfo(projectDetailInfo);\n }\n }),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [\n bidPackageNotes$,\n hidePageLoadingOverlay,\n keyboardShortcutsInfoIsOpen$,\n loadProjectDetailInfo,\n lockBidPackage$,\n onBidPackageLockChange,\n openBidPackageNotes,\n projectDetailInfo,\n showPageLoadingOverlay,\n showProjectInfo,\n viewProjectInfo$,\n ]);\n\n // Grid section - header\n useEffect(() => {\n setGridSection_Header(\n generateBidPackage_Header_GridSection(\n selectedBidPackage?.isGeneralCondition ?? false,\n isReadOnly,\n selectedBidPackage?.bidders,\n ),\n );\n }, [\n generateBidPackage_Header_GridSection,\n isReadOnly,\n selectedBidPackage?.bidders,\n selectedBidPackage?.isGeneralCondition,\n ]);\n\n // Grid section - line items header\n useEffect(() => {\n setGridSection_LineItems_Header(\n generateBidPackage_LineItems_Header_GridSection({\n bidders: selectedBidPackage?.bidders || [],\n onBidderStatusChange: async (bidder: Bidder, status: BidderStatus) => {\n await executeCommand({\n commandToExecute: new SetBidderStatusCommand(\n selectedBidPackageId!,\n bidder.companyName!,\n status,\n ),\n commandExecutionType: 'relies-on-signal-r-for-completion',\n commandTimeoutFunction: loadBidPackageDetails,\n });\n },\n lineItemRollupBids: selectedBidPackage?.lineItemRollupBids || [],\n selectedBidderId: selectedBidPackage?.selectedBidderId,\n isReadOnly,\n // NOTE: We pass the count of ALL line items here, because this is used to show a warning icon\n // in the various line items headers (regular / alternates) when we have a lot of line items on the\n // page in general and performance may be affected\n lineItemsCountForSection:\n selectedBidPackage?.lineItems.filter((v) => !v.alternateId).length || 0,\n allLineItemsCount: selectedBidPackage?.lineItems.length || 0,\n }),\n );\n }, [\n editBidderNotes,\n executeCommand,\n generateBidPackage_LineItems_Header_GridSection,\n isReadOnly,\n loadBidPackageDetails,\n selectedBidPackageId,\n selectedBidPackage?.bidders,\n selectedBidPackage?.lineItemRollupBids,\n selectedBidPackage?.lineItems,\n selectedBidPackage?.lineItems.length,\n selectedBidPackage?.selectedBidderId,\n showBidderInfo,\n ]);\n\n // Grid section - line items\n useEffect(() => {\n if (!selectedBidPackage) {\n return;\n }\n\n const lineItemsGridSection = generateBidPackage_LineItems_GridSection({\n alternate: null,\n bidPackage: selectedBidPackage,\n gridSectionId: BidPackageConstants.GridSectionIds.LINE_ITEMS,\n isReadOnly: isReadOnly,\n lineItemRollupBids: BidPackage.getLineItemRollupBids(\n selectedBidPackage.lineItemRollupBids,\n null,\n ),\n lineItems: selectedBidPackage!.getLineItems(null),\n lineItemGroupOrders: selectedBidPackage!.getLineItemGroupOrders(null),\n projectInfo: projectInfo!,\n unitsOfMeasureDropdownListOptions: allUnitOfMeasureDropdownOptions,\n globalCollapseResponseKey: null,\n });\n\n if (lineItemsGridSection) {\n // Break apart the grid section that was just generated into new grid sections of x rows each.\n // By doing this, we can minimize the re-render impact when something like line items changes\n // and affects many different things on the page (line items, adjustments, totals, alternate line items, etc.).\n const numberOfRowsPerSection = 5;\n const numberOfRows = lineItemsGridSection.primaryGrid.rows.length;\n\n const numberOfNewGridSectionsToCreate = Math.ceil(numberOfRows / numberOfRowsPerSection);\n\n const newGridSections: BTGridSection[] = [];\n\n for (let i = 0; i < numberOfNewGridSectionsToCreate; i++) {\n newGridSections.push({\n id: `${lineItemsGridSection.id}${i}`,\n collapseOrSelectGroupingKey: lineItemsGridSection.id, // NOTE: We want the collapse grouping key to remain consistent between grid sections\n testId: `${lineItemsGridSection.testId}${i}`,\n primaryGrid: {\n addLeftPadding: lineItemsGridSection.primaryGrid.addLeftPadding,\n id: `${lineItemsGridSection.primaryGrid.id}${i}`,\n testId: `${lineItemsGridSection.primaryGrid.testId}${i}`,\n rows: lineItemsGridSection.primaryGrid.rows.slice(\n i * numberOfRowsPerSection,\n i * numberOfRowsPerSection + numberOfRowsPerSection,\n ),\n auxiliaryRows: lineItemsGridSection.primaryGrid.auxiliaryRows.slice(\n i * numberOfRowsPerSection,\n i * numberOfRowsPerSection + numberOfRowsPerSection,\n ),\n },\n secondaryGrids: lineItemsGridSection.secondaryGrids.map((currSecondaryGrid) => {\n return {\n addLeftPadding: currSecondaryGrid.addLeftPadding,\n id: `${currSecondaryGrid.id}${i}`,\n testId: `${currSecondaryGrid.testId}${i}`,\n rows: currSecondaryGrid.rows.slice(\n i * numberOfRowsPerSection,\n i * numberOfRowsPerSection + numberOfRowsPerSection,\n ),\n auxiliaryRows: currSecondaryGrid.auxiliaryRows.slice(\n i * numberOfRowsPerSection,\n i * numberOfRowsPerSection + numberOfRowsPerSection,\n ),\n };\n }),\n });\n }\n\n setGridSections_LineItems(newGridSections);\n } else {\n setGridSections_LineItems([]);\n }\n }, [\n generateBidPackage_LineItems_GridSection,\n selectedBidPackage,\n allUnitOfMeasureDropdownOptions,\n isReadOnly,\n projectInfo,\n ]);\n\n // Grid section - adjustments\n useEffect(() => {\n if (!selectedBidPackage) {\n return;\n }\n\n const gridSectionId = `${BidPackageConstants.GridSectionIds.LINE_ITEMS} - Adjustments`;\n\n setGridSection_LineItems_Adjustments(\n generateBidPackage_Adjustments_GridSection({\n allowEntryInAdjustmentsRow: true,\n alternate: null,\n bidPackage: selectedBidPackage!,\n collapseShouldIncludeAdjustmentsHeaderRow: false,\n gridSectionId,\n isBidPackageTotalsSection: false,\n projectAlternates: projectInfo!.alternates,\n showTopBorders: false,\n totalsTitle: t('general:totals'),\n isReadOnly,\n globalCollapseResponseKey: null,\n }),\n );\n }, [generateBidPackage_Adjustments_GridSection, projectInfo, selectedBidPackage, t, isReadOnly]);\n\n // Grid section - totals\n useEffect(() => {\n if (!selectedBidPackage) {\n return;\n }\n\n const gridSectionId = BidPackageConstants.GridSectionIds.BID_PACKAGE_TOTALS;\n\n const totalsGridSection = generateBidPackage_Adjustments_GridSection({\n allowEntryInAdjustmentsRow: false,\n alternate: null,\n bidPackage: selectedBidPackage!,\n collapseShouldIncludeAdjustmentsHeaderRow: true,\n gridSectionId,\n isBidPackageTotalsSection: true,\n projectAlternates: projectInfo!.alternates,\n showTopBorders: true,\n totalsTitle: t('bid-package:bidPackageTotals'),\n isReadOnly,\n globalCollapseResponseKey: `${GlobalCollapseResponseKeyPrefix}BidPackageTotals`,\n });\n\n totalsGridSection!.addTopMargin = true;\n\n setGridSection_BidPackageTotals(totalsGridSection);\n }, [generateBidPackage_Adjustments_GridSection, selectedBidPackage, projectInfo, t, isReadOnly]);\n\n // Grid section - requirements\n useEffect(() => {\n if (selectedBidPackage?.isGeneralCondition ?? false) {\n setGridSection_GeneralRequirements(null);\n setGridSection_TradeRequirements(null);\n return;\n }\n\n setGridSection_GeneralRequirements(\n generateBidPackage_Requirements_GridSection(\n selectedBidPackage?.bidders || [],\n selectedBidPackage?.requirements || [],\n selectedBidPackage?.selectedBidderId,\n `${BidPackageConstants.GridSectionIds.REQUIREMENTS} - General`,\n 'general',\n isReadOnly,\n ),\n );\n\n setGridSection_TradeRequirements(\n generateBidPackage_Requirements_GridSection(\n selectedBidPackage?.bidders || [],\n selectedBidPackage?.requirements || [],\n selectedBidPackage?.selectedBidderId,\n `${BidPackageConstants.GridSectionIds.REQUIREMENTS} - Trade`,\n 'trade',\n isReadOnly,\n ),\n );\n }, [\n generateBidPackage_Requirements_GridSection,\n selectedBidPackage?.isGeneralCondition,\n isReadOnly,\n selectedBidPackage?.bidders,\n selectedBidPackage?.requirements,\n selectedBidPackage?.selectedBidderId,\n ]);\n\n // Grid section - alternates\n useEffect(() => {\n if (!selectedBidPackage) {\n return;\n }\n\n const alternatesGridSections: BTGridSection[] = [];\n\n // Alternates are defined on the project, and line items tie back to alternates if they are marked as part of one\n sortBy(projectInfo?.alternates, (v) => v.name).forEach((currAlternate) => {\n // NOTE: We want to show alternates sections even if they don't have any line items\n\n const gridSectionId1 = `${BidPackageConstants.GridSectionIds.LINE_ITEMS} - Alternate - ${currAlternate.id}`;\n\n // NOTE: This generates the grid section, including the primary and secondary subgrids\n const lineItemsAlternatesGridSection = generateBidPackage_LineItems_GridSection({\n alternate: currAlternate,\n bidPackage: selectedBidPackage,\n gridSectionId: gridSectionId1,\n isReadOnly: isReadOnly,\n lineItemRollupBids: BidPackage.getLineItemRollupBids(\n selectedBidPackage.lineItemRollupBids,\n currAlternate.id!,\n ),\n lineItems: selectedBidPackage.getLineItems(currAlternate.id!),\n lineItemGroupOrders: selectedBidPackage.getLineItemGroupOrders(currAlternate.id!),\n projectInfo: projectInfo!,\n unitsOfMeasureDropdownListOptions: allUnitOfMeasureDropdownOptions,\n globalCollapseResponseKey: `${GlobalCollapseResponseKeyPrefix}${currAlternate.id}`,\n });\n\n // NOTE: We pass the count of ALL line items here, because this is used to show a warning icon\n // in the various line items headers (regular / alternates) when we have a lot of line items on the\n // page in general and performance may be affected\n const allLineItemsCount = selectedBidPackage.lineItems.length || 0;\n const lineItemsCountForSection =\n selectedBidPackage.lineItems.filter((v) => v.alternateId === currAlternate.id).length || 0;\n\n // Generate the header rows for the primary / secondary subgrids.\n // NOTE: The way we build things here is different than the way we do it elsewhere.\n // In this code, we generate rows and set them on existing subgrids, from left to right.\n const alternateHeaderRows = generateLineItemsAlternatesGridSectionHeaderRows({\n bidPackage: selectedBidPackage!,\n gridSectionId: gridSectionId1,\n alternate: currAlternate,\n isReadOnly: isReadOnly,\n allLineItemsCount,\n lineItemsCountForSection,\n });\n\n // Add in a secondary header row to serve as the row for the edit/delete hamburger icon\n const alternateHeaderRowExtensions = generateLineItemsAlternatesGridSectionHeaderRowExtensions(\n {\n bidPackage: selectedBidPackage!,\n gridSectionId: gridSectionId1,\n alternate: currAlternate,\n isReadOnly: isReadOnly,\n allLineItemsCount,\n lineItemsCountForSection,\n },\n );\n\n // Add in the primary grid header row and its extension\n lineItemsAlternatesGridSection?.primaryGrid.rows.unshift(\n ...[alternateHeaderRows.primaryRow, alternateHeaderRowExtensions.primaryRow],\n );\n\n // Add in the secondary grid header rows we just got to the various subgrids\n for (let i = 0; i < alternateHeaderRows.secondaryGridRows.length; i++) {\n lineItemsAlternatesGridSection?.secondaryGrids[i]?.rows?.unshift(\n alternateHeaderRows.secondaryGridRows[i],\n );\n }\n\n // Add in the secondary grid header row extensions for the various subgrids\n for (let i = 0; i < alternateHeaderRowExtensions.secondaryGridRows.length; i++) {\n lineItemsAlternatesGridSection?.secondaryGrids[i]?.rows?.unshift(\n alternateHeaderRowExtensions.secondaryGridRows[i],\n );\n }\n\n lineItemsAlternatesGridSection!.addTopMargin = true;\n\n if (lineItemsAlternatesGridSection) {\n // Break apart the grid section that was just generated into new grid sections of x rows each.\n // By doing this, we can minimize the re-render impact when something like line items changes\n // and affects many different things on the page (line items, adjustments, totals, alternate line items, etc.).\n const numberOfRowsPerSection = 5;\n const numberOfRows = lineItemsAlternatesGridSection.primaryGrid.rows.length;\n\n const numberOfNewGridSectionsToCreate = Math.ceil(numberOfRows / numberOfRowsPerSection);\n\n const newGridSections: BTGridSection[] = [];\n\n for (let i = 0; i < numberOfNewGridSectionsToCreate; i++) {\n newGridSections.push({\n id: `${lineItemsAlternatesGridSection.id}${i}`,\n collapseOrSelectGroupingKey: lineItemsAlternatesGridSection.id, // NOTE: We want the collapse grouping key to remain consistent between grid sections\n testId: `${lineItemsAlternatesGridSection.testId}${i}`,\n addTopMargin: i === 0,\n primaryGrid: {\n addLeftPadding: lineItemsAlternatesGridSection.primaryGrid.addLeftPadding,\n id: `${lineItemsAlternatesGridSection.primaryGrid.id}${i}`,\n testId: `${lineItemsAlternatesGridSection.primaryGrid.testId}${i}`,\n rows: lineItemsAlternatesGridSection.primaryGrid.rows.slice(\n i * numberOfRowsPerSection,\n i * numberOfRowsPerSection + numberOfRowsPerSection,\n ),\n auxiliaryRows: lineItemsAlternatesGridSection.primaryGrid.auxiliaryRows.slice(\n i * numberOfRowsPerSection,\n i * numberOfRowsPerSection + numberOfRowsPerSection,\n ),\n },\n secondaryGrids: lineItemsAlternatesGridSection.secondaryGrids.map(\n (currSecondaryGrid) => {\n return {\n addLeftPadding: currSecondaryGrid.addLeftPadding,\n id: `${currSecondaryGrid.id}${i}`,\n testId: `${currSecondaryGrid.testId}${i}`,\n rows: currSecondaryGrid.rows.slice(\n i * numberOfRowsPerSection,\n i * numberOfRowsPerSection + numberOfRowsPerSection,\n ),\n auxiliaryRows: currSecondaryGrid.auxiliaryRows.slice(\n i * numberOfRowsPerSection,\n i * numberOfRowsPerSection + numberOfRowsPerSection,\n ),\n };\n },\n ),\n });\n }\n\n alternatesGridSections.push(...newGridSections);\n }\n\n const gridSectionId2 = `${BidPackageConstants.GridSectionIds.ADJUSTMENTS} - Alternate - ${currAlternate.id}`;\n\n // For each alternate, we are going to have adjustments, so add those grid sections in\n const adjustmentsGridSection = generateBidPackage_Adjustments_GridSection({\n allowEntryInAdjustmentsRow: true,\n alternate: currAlternate,\n bidPackage: selectedBidPackage!,\n collapseShouldIncludeAdjustmentsHeaderRow: false,\n gridSectionId: gridSectionId2,\n isBidPackageTotalsSection: false,\n projectAlternates: projectInfo!.alternates,\n showTopBorders: false,\n totalsTitle: `Total ${currAlternate.name}`,\n isReadOnly,\n globalCollapseResponseKey: `${GlobalCollapseResponseKeyPrefix}${currAlternate.id}`,\n });\n\n alternatesGridSections.push(adjustmentsGridSection!);\n });\n\n setGridSections_Alternates(alternatesGridSections);\n }, [\n allUnitOfMeasureDropdownOptions,\n generateBidPackage_Adjustments_GridSection,\n generateBidPackage_LineItems_GridSection,\n generateLineItemsAlternatesGridSectionHeaderRows,\n generateLineItemsAlternatesGridSectionHeaderRowExtensions,\n isReadOnly,\n projectInfo,\n selectedBidPackage,\n ]);\n\n useEffect(() => {\n const newGridSections: (BTGridSection | null)[] = [\n // Main line items section\n gridSection_Header,\n gridSection_LineItems_Header,\n ...gridSections_LineItems,\n gridSection_TradeRequirements,\n gridSection_GeneralRequirements,\n gridSection_LineItems_Adjustments,\n // Alternates section(s)\n ...gridSections_Alternates,\n // Totals section\n gridSection_BidPackageTotals,\n ];\n\n const newGridSections2 = newGridSections.filter((v) => v !== null) as BTGridSection[];\n\n setGridSections(newGridSections2);\n }, [\n gridSection_BidPackageTotals,\n gridSection_GeneralRequirements,\n gridSection_Header,\n gridSections_LineItems,\n gridSection_LineItems_Adjustments,\n gridSection_LineItems_Header,\n gridSection_TradeRequirements,\n gridSections_Alternates,\n ]);\n\n const onLineItemsAddedOrEdited = useCallback(\n async (commands: ICommand[]) => {\n // If the user added a lot of line items, show them a message since it can take\n // a while for them to all get through the event processor and make it back to the UI\n if (commands.length > BidPackageConstants.BID_PACKAGE_LINEITEMS_ADD_THRESHOLD) {\n showInfoNotification(\n t('bid-package:largeNumberOfLineItems_Title'),\n t('bid-package:largeNumberOfLineItems_Message', {\n lineItemsCount: commands.length,\n }),\n );\n }\n\n if (!commands.length) {\n showInfoNotification(t('general:noChanges'), t('bid-package:noChangesWereFound'));\n return;\n }\n\n const functionToExecute = async (): Promise => {\n if (lineItemsModalState.mode === 'add') {\n const addCommands = commands.map((c) => c as AddLineItemToBidPackageCommand);\n await BidPackageApi.addLineItemsToBidPackage(addCommands);\n } else {\n const updateCommands = commands.map((c) => c as UpdateBidPackageLineItemCommand);\n await BidPackageApi.updateBidPackageLineItems(updateCommands);\n }\n };\n\n await executeCommand({\n commandToExecute: functionToExecute,\n commandExecutionType: 'relies-on-signal-r-for-completion',\n commandSuccessCallback: () => {\n // Only close the modal if things succeeded\n setLineItemsModalState((state) => {\n return { ...state, isOpen: false };\n });\n },\n commandTimeoutFunction: loadBidPackageDetails,\n });\n },\n [executeCommand, loadBidPackageDetails, showInfoNotification, t, lineItemsModalState.mode],\n );\n\n const onLineItemsDiscard = useCallback(\n (lineItemsToEdit: LineItemInfo[]) => {\n if (\n (lineItemsModalState.mode === 'add' && !lineItemsToEdit.length) ||\n (lineItemsModalState.mode === 'edit' && !lineItemsToEdit.some((li) => li.changed))\n ) {\n setLineItemsModalState((state) => {\n return { ...state, isOpen: false };\n });\n } else {\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: (): void => {\n setLineItemsModalState((state) => {\n return { ...state, isOpen: false };\n });\n hideConfirmationOverlay();\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n }\n },\n [\n lineItemsModalState,\n setLineItemsModalState,\n hideConfirmationOverlay,\n showConfirmationOverlay,\n t,\n ],\n );\n\n const onLineItemsChange = useCallback((itemsChanged: boolean) => {\n addEditLineItemsFormIsDirty.current = itemsChanged;\n }, []);\n\n const onAddEditOnLineItemsModalClosing = useCallback(() => {\n setLineItemsModalState((state) => {\n return { ...state, isOpen: false };\n });\n }, []);\n\n const onAddEditOnLineItemsDiscard = useCallback((): Promise => {\n if (addEditLineItemsFormIsDirty.current) {\n return new Promise((resolve) => {\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: (): void => {\n hideConfirmationOverlay();\n resolve(true);\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n resolve(false);\n },\n color: 'gray',\n },\n ],\n });\n });\n } else {\n return Promise.resolve(true);\n }\n }, [hideConfirmationOverlay, showConfirmationOverlay, t]);\n\n const onSelectedBidPackageChange = useCallback(\n (newValue: unknown): void => {\n const matchingBidPackage = allBidPackageDropdownOptions.find((v) => v.value === newValue);\n if (matchingBidPackage) {\n // When we change the selected bid package, we want to navigate to this same page but with a URL containing\n // the new bid package ID.\n // NOTE: The routing code is configured to unmount / remount this page component when the URL changes.\n history.push(`${ApplicationRoutes.BID_PACKAGE}/${matchingBidPackage.value}`);\n }\n },\n [allBidPackageDropdownOptions, history],\n );\n\n const getBidPackageLockTooltip = useCallback((): string => {\n if (selectedBidPackage && lockedByUser !== undefined) {\n return currentUser!.email !== lockedByUser.email\n ? t('bid-package:bidPackageLocked', {\n user: lockedByUser.name ?? getEmailWithoutDomain(lockedByUser.email),\n })\n : t('bid-package:unlockBidPackage');\n }\n return canLockBidPackage\n ? t('bid-package:lockBidPackage')\n : t('bid-package:unableToLockBidPackage');\n }, [canLockBidPackage, currentUser, lockedByUser, selectedBidPackage, t]);\n\n const getFrozenEntitiesNames = (): string[] => {\n let returnValue: string[] = [];\n\n if (bidPackageIsFrozen) {\n returnValue.push(t('general:bidPackage'));\n }\n\n if (bidPackageNotesAreFrozen) {\n returnValue.push(t('bid-package:bidPackageNotes'));\n }\n\n // If we have bidder notes that are frozen, show the user the bidder name\n if (bidderNoteIdsThatAreFrozen.length > 0) {\n bidderNoteIdsThatAreFrozen.forEach((currFrozenNoteId) => {\n const matchingBidder = selectedBidPackage?.bidders.find(\n (m) => m.notesId === currFrozenNoteId,\n );\n\n if (matchingBidder) {\n returnValue.push(`${t('bid-package:bidderNote')} (${matchingBidder.companyName})`);\n }\n });\n }\n\n // If we have bidder document upload containers that are frozen, show the user the bidder name\n if (bidderFileUploadContainerIdsThatAreFrozen.length > 0) {\n bidderFileUploadContainerIdsThatAreFrozen.forEach((currFrozenFileUploadContainerId) => {\n const matchingBidder = selectedBidPackage?.bidders.find(\n (m) => m.fileUploadContainerId === currFrozenFileUploadContainerId,\n );\n\n if (matchingBidder) {\n returnValue.push(`${t('bid-package:bidderDocument')} (${matchingBidder.companyName})`);\n }\n });\n }\n\n // If we have adjustment notes that are frozen, show the user the alternate name (if applicable)\n if (adjustmentNoteIdsThatAreFrozen.length > 0) {\n adjustmentNoteIdsThatAreFrozen.forEach((currFrozenAdjustmentNoteId) => {\n const matchingAdjustment = selectedBidPackage?.adjustments.find(\n (m) => m.notesId === currFrozenAdjustmentNoteId,\n );\n\n if (matchingAdjustment) {\n let matchingAlternateName = matchingAdjustment.alternateId\n ? projectInfo?.alternates.find((m) => m.id === matchingAdjustment.alternateId)?.name ||\n ''\n : '';\n\n matchingAlternateName = matchingAlternateName ? ` (${matchingAlternateName})` : '';\n\n returnValue.push(`${t('bid-package:adjustmentNote')}${matchingAlternateName}`);\n }\n });\n }\n\n returnValue = sortBy(returnValue, (v) => v);\n\n return returnValue;\n };\n\n const frozenEntitiesNameStrings = getFrozenEntitiesNames();\n\n return (\n <>\n {projectInfo ? (\n
    \n 0 ||\n bidderFileUploadContainerIdsThatAreFrozen.length > 0 ||\n adjustmentNoteIdsThatAreFrozen.length > 0\n }\n />\n\n {selectedBidPackageId && selectedBidPackage ? (\n <>\n {frozenEntitiesNameStrings.length > 0 ? (\n
    \n
    \n \n
    \n
    \n ) : (\n <>\n )}\n\n
    \n \n \n
    \n\n \n \n \n\n {getBidPackageNotesJSX(\n selectedBidPackage,\n isReadOnly,\n bidPackageNotesAreFrozen,\n onBidPackageNotesChangeCallback,\n )}\n\n {getBiddersAddEditJSX(selectedBidPackage)}\n\n {getBidderNotesJSX(\n isReadOnly,\n bidderNoteIdsThatAreFrozen.includes(\n selectedBidPackage.bidders.find(\n (v) => v.id === lastEditedBidderForBidderNotes?.id,\n )?.notesId || '',\n ),\n )}\n\n {getAdjustmentNotesJSX(\n isReadOnly,\n adjustmentNoteIdsThatAreFrozen.includes(\n selectedBidPackage.adjustments.find(\n (v) => v.id === lastEditedAdjustmentForAdjustmentNotes?.id,\n )?.notesId || '',\n ),\n projectInfo!.alternates,\n selectedBidPackage!.bidders,\n )}\n\n {getBidderInfoJSX()}\n\n {!bidderForDocumentsModal || !bidderForDocumentsModal.companyName ? (\n <>\n ) : (\n getBidderDocumentsModalJSX(\n projectInfo.id!,\n selectedBidPackageId,\n bidderForDocumentsModal.companyName,\n bidderForDocumentsModal?.fileUploadContainerId,\n onBidderDocumentsModalClose,\n isReadOnly,\n bidderFileUploadContainerIdsThatAreFrozen.includes(\n selectedBidPackage.bidders.find((v) => v.id === bidderForDocumentsModal?.id)\n ?.fileUploadContainerId || '',\n ),\n )\n )}\n
    \n \n ) : (\n <>\n )}\n\n {getProjectInfoJSX()}\n\n {\n setKeyboardShortcutsInfoIsOpen(false);\n }}\n provideFocusTrapCode\n addExtraSpaceAtBottom\n >\n \n \n\n {/* {isEnvironment('local') ? getClippyJSX() : <>} */}\n\n
    \n \n ) : (\n <>\n )}\n \n );\n};\n\nexport const GlobalCollapseResponseKeyPrefix = 'Global Collapse Key - ';\n\nexport const BidderGridRowSortableContainerId = 'bidders';\n\nexport const LineItemGridRowSortableContainerId = 'lineItemsSortableContainer';\n\nconst BidPackagePage: React.FC = () => {\n return (\n \n \n \n \n \n );\n};\n\nexport default BidPackagePage;\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class AddEditProjectNotesToProjectCommand extends CommandBase {\r\n constructor(public projectId: string, public projectNotesId: string | null, public text: string) {\r\n super(\r\n 'DESTINI.BidDay.Commands.Projects.AddEditProjectNotes',\r\n `/project/${projectId}/notes`,\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class CloseProjectCommand extends CommandBase {\r\n constructor(public id: string) {\r\n super('DESTINI.BidDay.Commands.CloseProject', 'project/close-project', 'post');\r\n }\r\n}\r\n","import { CommandBase } from '../../CommandBase';\n\nexport class AddProjectFeeCommand extends CommandBase {\n constructor(\n public projectId: string,\n public name: string,\n public feeType: number,\n public value: number,\n public referenceFeeName?: string,\n ) {\n super('DESTINI.BidDay.Commands.Projects.Fees.AddProjectFee', '', 'post');\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class DeleteProjectFeeCommand extends CommandBase {\n constructor(public projectId: string, public name: string) {\n super('DESTINI.BidDay.Commands.Projects.Fees.DeleteProjectFee', '', 'post');\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateProjectFeeCommand extends CommandBase {\n constructor(\n public projectId: string,\n public originalName: string,\n public name?: string,\n public feeType?: number,\n public value?: number,\n public referenceFeeName?: string,\n ) {\n super('DESTINI.BidDay.Commands.Projects.Fees.UpdateProjectFee', '', 'post');\n }\n}\n","import { CommandBase } from '../../CommandBase';\n\nexport class UpdateProjectFeeOrderCommand extends CommandBase {\n constructor(public projectId: string, public name: string, public order: number) {\n super('DESTINI.BidDay.Commands.Projects.Fees.UpdateProjectFeeOrder', '', 'post');\n }\n}\n","import { CommandBatchBase } from '../../CommandBatchBase';\nimport { AddProjectFeeCommand } from './add-project-fee-command';\nimport { DeleteProjectFeeCommand } from './delete-project-fee-command';\nimport { UpdateProjectFeeCommand } from './update-project-fee-command';\nimport { UpdateProjectFeeOrderCommand } from './update-project-fee-order-command';\n\nconst allowedCommands = [\n AddProjectFeeCommand,\n DeleteProjectFeeCommand,\n UpdateProjectFeeCommand,\n UpdateProjectFeeOrderCommand,\n];\n\nexport class ProjectFeesBatchCommand extends CommandBatchBase {\n constructor() {\n super('Project', '/project/fees', 'post', allowedCommands);\n }\n}\n","import React, { useContext } from 'react';\r\nimport { Observable } from 'rxjs';\r\nimport { useObservable, useObservableWithValue } from '../../../../hooks/observables/useObservable';\r\nimport { BidSummaryOptions } from './BidSummaryPage';\r\n\r\ninterface BidSummaryPageContextInterface {\r\n alternateChange$: Observable;\r\n bidAmountBlur$: Observable;\r\n bidAmountChange$: Observable;\r\n bidSummaryDisplayOptionsChange$: Observable;\r\n contingencyBlur$: Observable;\r\n contingencyChange$: Observable;\r\n feeAmountBlur$: Observable;\r\n feeAmountChange$: Observable;\r\n feeCalculationRequest$: Observable;\r\n feesEdit$: Observable;\r\n keyboardShortcutsShow$: Observable;\r\n projectClose$: Observable;\r\n projectEditBiddersRanges$: Observable;\r\n projectEditNotes$: Observable;\r\n projectExportExcel$: Observable;\r\n projectShowInfo$: Observable;\r\n\r\n alternate_Change: (value: UpdateAlternateEnabledStatusValue) => void;\r\n bidAmount_Blur: (bidValue: BidAmountValue) => void;\r\n bidAmount_Change: (bidValue: BidAmountValue) => void;\r\n bidSummary_DisplayOptionsChange: (newBidSummaryOptions: BidSummaryOptions) => void;\r\n contingency_Blur: (bidPackageContingencyAmount: BidPackageContingencyValue) => void;\r\n contingency_Change: (bidPackageContingencyAmount: BidPackageContingencyValue) => void;\r\n feeAmount_Blur: (feeAndAmount: FeeNameAndAmount) => void;\r\n feeAmount_Change: (feeAndAmount: FeeNameAndAmount) => void;\r\n feeCalculation_Request: () => void;\r\n fees_Edit: () => void;\r\n keyboardShortcuts_Show: () => void;\r\n project_Close: () => void;\r\n project_EditBiddersRanges: (value: ProjectBiddersRanges) => void;\r\n project_EditNotes: () => void;\r\n project_ExportExcel: () => void;\r\n project_ShowInfo: (project: DetailProjectInfo) => void;\r\n}\r\n\r\nconst BidSummaryPageContext = React.createContext(\r\n {} as BidSummaryPageContextInterface,\r\n);\r\n\r\nconst BidSummaryPageContextProvider: React.FC = ({ children }) => {\r\n const [alternateChange$, alternate_Change] = useObservableWithValue<\r\n UpdateAlternateEnabledStatusValue\r\n >();\r\n\r\n const [bidAmountBlur$, bidAmount_Blur] = useObservableWithValue();\r\n\r\n const [bidAmountChange$, bidAmount_Change] = useObservableWithValue();\r\n\r\n const [contingencyBlur$, contingency_Blur] = useObservableWithValue();\r\n\r\n const [contingencyChange$, contingency_Change] = useObservableWithValue<\r\n BidPackageContingencyValue\r\n >();\r\n\r\n const [feesEdit$, fees_Edit] = useObservable();\r\n\r\n const [keyboardShortcutsShow$, keyboardShortcuts_Show] = useObservable();\r\n\r\n const [feeAmountBlur$, feeAmount_Blur] = useObservableWithValue();\r\n\r\n const [feeAmountChange$, feeAmount_Change] = useObservableWithValue();\r\n\r\n const [bidSummaryDisplayOptionsChange$, bidSummary_DisplayOptionsChange] = useObservableWithValue<\r\n BidSummaryOptions\r\n >();\r\n\r\n const [projectClose$, project_Close] = useObservable();\r\n\r\n const [projectEditBiddersRanges$, project_EditBiddersRanges] = useObservableWithValue<\r\n ProjectBiddersRanges\r\n >();\r\n\r\n const [projectEditNotes$, project_EditNotes] = useObservable();\r\n\r\n const [projectExportExcel$, project_ExportExcel] = useObservable();\r\n\r\n const [projectShowInfo$, project_ShowInfo] = useObservableWithValue();\r\n\r\n const [feeCalculationRequest$, feeCalculation_Request] = useObservable();\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nexport const useBidSummaryPageContext = (): BidSummaryPageContextInterface =>\r\n useContext(BidSummaryPageContext);\r\n\r\nexport default useBidSummaryPageContext;\r\n\r\nexport { BidSummaryPageContextProvider };\r\n","import React, { useRef } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport KeyboardShortcutsInformation, {\r\n KeyboardShortcutsInformation_Info,\r\n} from '../../../../common-page-components/keyboard-shortcuts-info/KeyboardShortcutsInformation';\r\n\r\nconst BidSummaryKeyboardShortcuts: React.FC = () => {\r\n const { t } = useTranslation();\r\n\r\n const keyboardShortcutsInfo = useRef({\r\n title: t('general:keyboardShortcuts'),\r\n groups: [\r\n {\r\n title: t('general:general'),\r\n listings: [\r\n {\r\n keys: [['Tab']],\r\n title: t('general:keyboardShortcuts_JumpToNextCell'),\r\n },\r\n {\r\n keys: [['Shift', 'Tab']],\r\n title: t('general:keyboardShortcuts_JumpToPreviousCell'),\r\n },\r\n {\r\n keys: [[{ key: 'arrow-up' }]],\r\n title: t('general:keyboardShortcuts_JumpToCellAbove'),\r\n },\r\n {\r\n keys: [[{ key: 'arrow-down' }], ['Enter']],\r\n title: t('general:keyboardShortcuts_JumpToCellBelow'),\r\n },\r\n ],\r\n },\r\n ],\r\n });\r\n\r\n return (\r\n <>\r\n \r\n \r\n );\r\n};\r\n\r\nexport default BidSummaryKeyboardShortcuts;\r\n","import { useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AddProjectFeeCommand } from '../../../../../../classes/commands/project/fees/add-project-fee-command';\nimport { DeleteProjectFeeCommand } from '../../../../../../classes/commands/project/fees/delete-project-fee-command';\nimport { ProjectFeesBatchCommand } from '../../../../../../classes/commands/project/fees/project-fees-batch-command';\nimport { UpdateProjectFeeCommand } from '../../../../../../classes/commands/project/fees/update-project-fee-command';\nimport { UpdateProjectFeeOrderCommand } from '../../../../../../classes/commands/project/fees/update-project-fee-order-command';\nimport { Alternate } from '../../../../../../classes/odata/alternate';\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\nimport { Fee } from '../../../../../../classes/odata/fee';\nimport { Project } from '../../../../../../classes/odata/project';\nimport { FeeApi } from '../../../../../../services';\nimport { useLogger } from '../../../../../../services/logger/Logger';\nimport { convertFeeTypeToFeeTypeOption } from '../../../../../../utils/feeLabel';\nimport { Fee as FeeTableFee } from '../../../../../common-page-components/fee-table/FeeTable';\nimport { NotificationPanelContext } from '../../../../../common-page-components/notification-panel/NotificationPanelContext';\nimport useCommandServiceHelper from '../../../../../shared-page-components/hooks/useCommandServiceHelper';\n\ninterface ReturnValue {\n feeTableFees: FeeTableFee[];\n addFeeCallback: (fee: FeeTableFee) => void;\n deleteFeeCallback: (fee: FeeTableFee) => void;\n updateFeeCallback: (fee: FeeTableFee, updatedFee: FeeTableFee) => void;\n onSortEndCallback: (fee: FeeTableFee, index: number) => void;\n calculateFeesCallback: (updatedFees: FeeTableFee[], baseCost: number) => Promise;\n onSaveClick: () => Promise;\n discardCallback: () => void;\n setFeeTableFeesNeedToBeCalculated: React.Dispatch>;\n}\n\nconst useFeeTable = (\n isProjectAdmin: boolean,\n projectId: string,\n projectFees: Fee[],\n bidPackages: BidPackage[],\n alternates: Alternate[],\n): ReturnValue => {\n const { t } = useTranslation();\n const logger = useLogger();\n const { showErrorNotification, showInfoNotification } = useContext(NotificationPanelContext);\n const { executeCommand } = useCommandServiceHelper();\n\n const batchCommand = useRef(new ProjectFeesBatchCommand());\n\n const [feeTableFees, setFeeTableFees] = useState([]);\n const [feeTableFeesNeedToBeCalculated, setFeeTableFeesNeedToBeCalculated] = useState(\n true,\n );\n const recalculatingFeeTableFees = useRef(false);\n\n const addFeeCallback = useCallback(\n (fee: FeeTableFee) => {\n batchCommand.current.addCommand(\n new AddProjectFeeCommand(\n projectId,\n fee.name.trim(),\n fee.feeType.value,\n fee.amount,\n fee.referenceFee,\n ),\n );\n },\n [projectId],\n );\n\n const deleteFeeCallback = useCallback(\n (fee: FeeTableFee) => {\n batchCommand.current.addCommand(\n new DeleteProjectFeeCommand(projectId, fee.name),\n );\n },\n [projectId],\n );\n\n const updateFeeCallback = useCallback(\n (fee: FeeTableFee, updatedFee: FeeTableFee) => {\n const newName = fee.name === updatedFee.name ? undefined : updatedFee.name;\n const newFeeTypeId =\n fee.feeType.value === updatedFee.feeType.value ? undefined : updatedFee.feeType.value;\n const newAmount = fee.amount === updatedFee.amount ? undefined : updatedFee.amount;\n const newReferenceFeeName =\n fee.referenceFee === updatedFee.referenceFee ? undefined : updatedFee.referenceFee;\n\n batchCommand.current.addCommand(\n new UpdateProjectFeeCommand(\n projectId,\n fee.name,\n newName?.trim(),\n newFeeTypeId,\n newAmount,\n newReferenceFeeName,\n ),\n );\n },\n [projectId],\n );\n\n const onSortEndCallback = useCallback(\n (fee: FeeTableFee, index: number) => {\n batchCommand.current.addCommand(\n new UpdateProjectFeeOrderCommand(projectId, fee.name, index),\n );\n },\n [projectId],\n );\n\n const calculateFeesCallback = useCallback(\n async (fees: FeeTableFee[], baseCost: number): Promise => {\n try {\n const feeDtos: FeeDTO[] = fees.map((fee) => ({\n name: fee.name,\n order: fee.order,\n feeType: fee.feeType.value,\n amount: fee.amount,\n referenceFeeName: fee.referenceFee,\n value: fee.total,\n }));\n\n const calculatedFees = await FeeApi.calculateFeesForGrid({\n fees: feeDtos,\n baseCost: baseCost,\n });\n\n const updatedFees: FeeTableFee[] = fees.map((fee) => {\n const calculatedFee = calculatedFees.find((f) => f.name === fee.name);\n if (!calculatedFee) {\n return fee;\n }\n\n return { ...fee, total: calculatedFee.value };\n });\n\n return updatedFees;\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('fees:calculationError'));\n return fees;\n }\n },\n [logger, showErrorNotification, t],\n );\n\n const onSaveClick = useCallback(async (): Promise => {\n const commands = batchCommand.current.getCommands();\n if (commands.length === 0) {\n showInfoNotification(t('general:noChanges'), t('general:noChangesWereMade'));\n return true;\n }\n\n try {\n const success = await executeCommand({\n commandToExecute: batchCommand.current,\n commandExecutionType: 'relies-on-signal-r-for-completion',\n });\n\n if (success) {\n batchCommand.current.clearCommands();\n }\n\n return success;\n } catch (error) {\n logger.logError(error);\n showErrorNotification(t('general:error'), t('fees:updateError'));\n return false;\n }\n }, [executeCommand, logger, showErrorNotification, showInfoNotification, t]);\n\n const discardCallback = useCallback(() => {\n batchCommand.current.clearCommands();\n }, []);\n\n // calculate the fees, based on the current bid total.\n useEffect(() => {\n const calculateFeeTableFees = async (): Promise => {\n // Don't calculate fees unless the user is project admin\n if (!isProjectAdmin) {\n setFeeTableFeesNeedToBeCalculated(false);\n recalculatingFeeTableFees.current = false;\n return;\n }\n\n recalculatingFeeTableFees.current = true;\n try {\n const calculatedFees = await FeeApi.calculateFeesForGrid({\n fees: projectFees.map((fee) => ({\n name: fee.name!,\n order: fee.order!,\n feeType: fee.feeType!,\n amount: fee.amount!,\n referenceFeeName: fee.referenceFeeName,\n value: 0,\n })),\n baseCost: Project.calculateProjectBidTotal(bidPackages, alternates),\n });\n\n setFeeTableFees(\n projectFees.map((fee) => ({\n id: fee.id!,\n order: fee.order!,\n name: fee.name!,\n amount: fee.amount!,\n feeType: convertFeeTypeToFeeTypeOption(t, fee.feeType!, fee.referenceFeeName),\n referenceFee: fee.referenceFeeName,\n total: calculatedFees.find((cf) => cf.name === fee.name)?.value || 0,\n isNew: false,\n })),\n );\n } catch (error) {\n logger.logError(error);\n setFeeTableFees(\n projectFees.map((fee) => ({\n id: fee.id!,\n order: fee.order!,\n name: fee.name!,\n amount: fee.amount!,\n feeType: convertFeeTypeToFeeTypeOption(t, fee.feeType!, fee.referenceFeeName),\n referenceFee: fee.referenceFeeName,\n total: 0,\n isNew: false,\n })),\n );\n } finally {\n setFeeTableFeesNeedToBeCalculated(false);\n recalculatingFeeTableFees.current = false;\n }\n };\n\n if (feeTableFeesNeedToBeCalculated && !recalculatingFeeTableFees.current) {\n if (projectFees?.length > 0) {\n calculateFeeTableFees();\n } else if (!projectFees.length) {\n setFeeTableFees([]);\n }\n }\n }, [\n alternates,\n bidPackages,\n t,\n projectFees,\n feeTableFeesNeedToBeCalculated,\n logger,\n isProjectAdmin,\n ]);\n\n return {\n feeTableFees,\n addFeeCallback,\n deleteFeeCallback,\n updateFeeCallback,\n onSortEndCallback,\n calculateFeesCallback,\n onSaveClick,\n discardCallback,\n setFeeTableFeesNeedToBeCalculated,\n };\n};\n\nexport default useFeeTable;\n","import { CommandBase } from '../CommandBase';\n\nexport class UpdateProjectBiddersRangesCommand extends CommandBase {\n constructor(\n public projectId: string,\n public lowBiddersMax: number,\n public midBiddersMax: number,\n ) {\n super(\n 'DESTINI.BidDay.Commands.Projects.UpdateProjectBiddersRanges',\n `/project/update-project-bidders-ranges`,\n 'post',\n );\n }\n}\n","import { connect, Form, Formik, FormikProps } from 'formik';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport * as Yup from 'yup';\nimport { getFormErrorMessages } from '../../../../../utils/forms';\nimport BTButton from '../../../../common-page-components/controls/button/BTButton';\nimport FormErrorContainer from '../../../../common-page-components/forms/form-error-container/FormErrorContainer';\nimport FormFooter from '../../../../common-page-components/forms/FormFooter';\nimport FormNumericTextInput from '../../../../common-page-components/forms/FormNumericTextInput';\nimport BTInput from '../../../../common-page-components/inputs/BTInput';\nimport './../../../../../styles/bidders-ranges-container.scss';\n\ninterface Props {\n projectBiddersRanges: ProjectBiddersRanges;\n isReadOnly: boolean;\n onSubmitClick: (projectBiddersRanges: ProjectBiddersRanges) => void;\n onDiscardClick: (projectBiddersRanges: ProjectBiddersRanges) => void;\n}\n\nconst ProjectBiddersRangesEditForm: React.FC = (props) => {\n const { t } = useTranslation();\n\n const FormSchema = Yup.object().shape({\n lowBiddersMax: Yup.number()\n .integer(t('bid-summary:lowRangeMaxWholeNumber')) //'The max of the low range must be a whole number')\n .typeError(t('bid-summary:lowRangeMaxRequired'))\n .min(0, t('bid-summary:lowRangeMaxAtLeastZero'))\n .max(1000, t('bid-summary:lowRangeMaxAtMostOneThousand'))\n .required(t('bid-summary:lowRangeMaxRequired')),\n midBiddersMax: Yup.number()\n .integer(t('bid-summary:midRangeMaxWholeNumber'))\n .typeError(t('bid-summary:midRangeMaxRequired'))\n .min(\n typeof Yup.ref('lowBiddersMax') === 'number' ? Number(Yup.ref('lowBiddersMax')) + 1 : 1,\n t('bid-summary:midRangeMaxGreaterThanLowRangeMax'),\n ) //this is so that we can have a low range.\n .max(1000, t('bid-summary:midRangeMaxAtMostOneThousand'))\n .required(t('bid-summary:midRangeMaxRequired')),\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const FormikEffect = connect((props: any) => {\n props.onFormChanged(props.formik);\n return null;\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onFormChanged = (form: FormikProps): void => {\n if (form && form.values) {\n const formProjectBiddersRanges = form.values as ProjectBiddersRanges;\n\n //the only time we need to auto adjust a range is when the low (red) bidders range pushes into the mid (yellow) bidders range and vice versa.\n //At that point, we need to make sure the mid(yellow) bidders range is +1 of the low(red) bidders max.\n if (\n formProjectBiddersRanges &&\n formProjectBiddersRanges.lowBiddersMax >= formProjectBiddersRanges.midBiddersMax\n ) {\n //add one to the mid max to allow for the mid range to be valid\n const newMidMax = formProjectBiddersRanges.lowBiddersMax + 1;\n if (formProjectBiddersRanges.midBiddersMax !== newMidMax) {\n //This is hella hacky, but for whatever reason if i do not use the 'setTimeout' call, i receive the error...\n //Warning: Cannot update a component (`Formik`) while rendering a different component (`Unknown`). To locate the bad setState() call inside `Unknown`, follow the stack trace as described in https://fb.me/setstate-in-render\n //For now, with the advice of another sr dev, using the setTimeout will allow me to conitnue with the story. We can revisit this later. - MR\n setTimeout(() => form.setFieldValue('midBiddersMax', newMidMax));\n }\n }\n }\n };\n\n return (\n
    \n {props.projectBiddersRanges && (\n \n {({ errors, values, submitCount }): JSX.Element => (\n <>\n \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n \n\n
    \n\n \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n\n
    \n \n\n
    \n\n \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n\n
    \n \n\n
    \n\n \n
    \n
    \n
    \n
    \n\n \n
    \n {props.isReadOnly ? (\n <>\n ) : (\n \n )}\n\n props.onDiscardClick(values)}\n />\n
    \n {submitCount > 0 && (\n \n )}\n
    \n
    \n \n )}\n \n )}\n
    \n );\n};\n\nexport default ProjectBiddersRangesEditForm;\n","import { isEqual } from 'lodash';\nimport React, { useCallback, useContext, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { UpdateProjectBiddersRangesCommand } from '../../../../../../classes/commands/project/update-project-bidders-ranges-command';\nimport { useLogger } from '../../../../../../services/logger/Logger';\nimport { ConfirmationOverlayContext } from '../../../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\nimport BTModal from '../../../../../common-page-components/modal/BTModal';\nimport { NotificationPanelContext } from '../../../../../common-page-components/notification-panel/NotificationPanelContext';\nimport ProjectBiddersRangesEditForm from '../../components/ProjectBiddersRangesEditForm';\n\n// defines the state object that the hook uses\ninterface ProjectBiddersRangesModalState {\n isOpen: boolean;\n projectId?: string;\n projectBiddersRangesToEdit?: ProjectBiddersRanges;\n isReadOnly: boolean;\n}\n\ninterface Props {\n projectId: string | undefined;\n onSubmitClickCallback: (\n newProjectBiddersRanges: ProjectBiddersRanges,\n commandToExecute: ICommand,\n ) => Promise;\n}\n\ninterface ReturnValue {\n setCurrentProjectBiddersRangesModalState: (\n newProjectBiddersRangesModalState: ProjectBiddersRangesModalState,\n ) => void;\n getProjectBiddersRangesModalJSX: () => JSX.Element;\n}\n\n// the hook\nconst useBidSummary_Settings_ProjectBiddersRangesModal = ({\n projectId,\n onSubmitClickCallback,\n}: Props): ReturnValue => {\n const { t } = useTranslation();\n\n const { showSuccessNotification, showInfoNotification, showErrorNotification } = useContext(\n NotificationPanelContext,\n );\n\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\n ConfirmationOverlayContext,\n );\n\n const [isOpen, setIsOpen] = useState(false);\n\n const [projectBiddersRangesToEdit, setProjectBiddersRangesToEdit] = useState<\n ProjectBiddersRanges | undefined\n >();\n\n const [isReadOnly, setIsReadOnly] = useState(false);\n\n const logger = useLogger();\n\n // allows the ability to set the hook modal state from outside of the hook.\n const setCurrentProjectBiddersRangesModalState = useCallback(\n (newProjectBiddersRangesModalState: ProjectBiddersRangesModalState) => {\n // lets set the individual variables\n setIsOpen(newProjectBiddersRangesModalState.isOpen);\n setProjectBiddersRangesToEdit(newProjectBiddersRangesModalState.projectBiddersRangesToEdit);\n setIsReadOnly(newProjectBiddersRangesModalState.isReadOnly);\n },\n [setIsOpen],\n );\n\n // handles what we do when the modal ui closes\n const onBiddersRangesModalClose = useCallback(() => {\n setIsOpen(false);\n }, [setIsOpen]);\n\n // handles when the user presses submit button\n const onSubmitClick = useCallback(\n async (newProjectBiddersRanges: ProjectBiddersRanges): Promise => {\n if (!projectId || !projectBiddersRangesToEdit) {\n logger.logError(\n new Error(\n \"Unable to continue with committing the changes to the project's bidders ranges. We are either missing the project id or the current bidders ranges to compare against.\",\n ),\n );\n showErrorNotification(t('general:error'), t('bid-summary:updateProjectBiddersRangesError'));\n return;\n }\n\n // If the current state of the project bidders ranges is different than the latest ranges, prompt the user\n if (isEqual(newProjectBiddersRanges, projectBiddersRangesToEdit)) {\n showInfoNotification(t('general:noChanges'), t('general:noChangesWereMade'));\n setIsOpen(false);\n return;\n }\n\n // lets create the command to be used to\n const result = await onSubmitClickCallback(\n newProjectBiddersRanges,\n new UpdateProjectBiddersRangesCommand(\n projectId,\n newProjectBiddersRanges.lowBiddersMax,\n newProjectBiddersRanges.midBiddersMax,\n ),\n );\n\n //regardless of what happened, we are going to hide the modal ui\n setIsOpen(false);\n\n // if we were successful, lets reset the hook. Otherwise leave it open\n if (result) {\n showSuccessNotification(\n t('general:success'),\n t('bid-summary:updateProjectBiddersRangesSuccess'),\n );\n } else {\n showErrorNotification(t('general:error'), t('bid-summary:updateProjectBiddersRangesError'));\n }\n },\n [\n projectId,\n projectBiddersRangesToEdit,\n onSubmitClickCallback,\n logger,\n showErrorNotification,\n t,\n showInfoNotification,\n showSuccessNotification,\n ],\n );\n\n const onDiscardClick = useCallback(\n (newProjectBiddersRanges: ProjectBiddersRanges) => {\n const discardChanges = () => {\n setIsOpen(false);\n };\n\n // If the current state of the project bidders ranges is different than the latest saved ranges, prompt the user\n if (!isEqual(newProjectBiddersRanges, projectBiddersRangesToEdit)) {\n showConfirmationOverlay({\n text: t('general:discardConfirmation'),\n buttons: [\n {\n text: t('general:discard'),\n onClick: (): void => {\n discardChanges();\n hideConfirmationOverlay();\n },\n color: 'normal',\n },\n {\n text: t('general:cancel'),\n onClick: (): void => {\n hideConfirmationOverlay();\n },\n color: 'gray',\n },\n ],\n });\n } else {\n discardChanges();\n }\n },\n [hideConfirmationOverlay, showConfirmationOverlay, t, projectBiddersRangesToEdit, setIsOpen],\n );\n\n // Get the modal UI for the number of bidders ranges\n const getProjectBiddersRangesModalJSX = useCallback((): JSX.Element => {\n return (\n
    \n {projectId && projectBiddersRangesToEdit ? (\n \n \n \n ) : (\n <>\n )}\n
    \n );\n }, [\n projectId,\n isOpen,\n projectBiddersRangesToEdit,\n onBiddersRangesModalClose,\n onSubmitClick,\n onDiscardClick,\n isReadOnly,\n ]);\n return {\n setCurrentProjectBiddersRangesModalState,\n getProjectBiddersRangesModalJSX,\n };\n};\n\nexport default useBidSummary_Settings_ProjectBiddersRangesModal;\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class SetContingencyOnBidPackageCommand extends CommandBase {\r\n constructor(public bidPackageId: string, public value: number) {\r\n super(\r\n 'DESTINI.BidDay.Commands.BidPackages.SetContingencyOnBidPackage',\r\n 'bid-package/set-contingency',\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { clone } from 'lodash';\r\nimport { SetAdjustmentOnBidPackageCommand } from '../../../../../classes/commands/bid-packages/set-adjustment-on-bid-package-command';\r\nimport { SetContingencyOnBidPackageCommand } from '../../../../../classes/commands/bid-packages/set-contingency-command-on-bid-package';\r\nimport { Alternate } from '../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\r\nimport { BidPackageBidTotal } from '../../../../../classes/odata/bid-package-bid-total';\r\nimport { normalizeNullOrUndefined } from '../../../../../utils/general';\r\nimport { areTrimmedStringsEqual } from '../../../../../utils/strings';\r\n\r\ninterface ReturnValue {\r\n onChangeCallback_BidAmount: (\r\n currBidPackages: BidPackage[],\r\n bidValue: BidAmountValue,\r\n ) => BidPackage[];\r\n\r\n onBlurCallback_BidAmount: (\r\n originalBidPackages: BidPackage[],\r\n currentBidPackages: BidPackage[],\r\n alternates: Alternate[],\r\n bidValue: BidAmountValue,\r\n ) => ICommand | null;\r\n\r\n onChangeCallback_Contingency: (\r\n currBidPackages: BidPackage[],\r\n bidPackageContingencyAmount: BidPackageContingencyValue,\r\n ) => BidPackage[];\r\n\r\n onBlurCallback_Contingency: (\r\n originalBidPackages: BidPackage[],\r\n currentBidPackages: BidPackage[],\r\n bidPackageContingencyAmount: BidPackageContingencyValue,\r\n ) => ICommand | null;\r\n\r\n // Updates the bid packages copy with the new data from the current bid packages\r\n successFunction_BidAmount: (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackagesToUpdate: BidPackage[],\r\n bidPackagesWithUpdatedData: BidPackage[],\r\n ) => BidPackage[];\r\n\r\n // Updates the current bid packages with the data from the bid packages copy\r\n errorFunction_BidAmount: (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackagesToUpdate: BidPackage[],\r\n bidPackagesWithUpdatedData: BidPackage[],\r\n ) => BidPackage[];\r\n\r\n // Updates the bid packages copy with the new data from the current bid packages\r\n successFunction_Contingency: (\r\n command: ICommand,\r\n bidPackagesToUpdate: BidPackage[],\r\n bidPackagesWithUpdatedData: BidPackage[],\r\n ) => BidPackage[];\r\n\r\n // Updates the current bid packages with the data from the bid packages copy\r\n errorFunction_Contingency: (\r\n command: ICommand,\r\n bidPackagesToUpdate: BidPackage[],\r\n bidPackagesWithUpdatedData: BidPackage[],\r\n ) => BidPackage[];\r\n}\r\n\r\nconst useBidSummary = (): ReturnValue => {\r\n return {\r\n onChangeCallback_BidAmount,\r\n onBlurCallback_BidAmount,\r\n onChangeCallback_Contingency,\r\n onBlurCallback_Contingency,\r\n successFunction_BidAmount,\r\n errorFunction_BidAmount,\r\n successFunction_Contingency,\r\n errorFunction_Contingency,\r\n };\r\n};\r\n\r\nconst onChangeCallback_BidAmount = (\r\n currBidPackages: BidPackage[],\r\n bidValue: BidAmountValue,\r\n): BidPackage[] => {\r\n const copy = [...currBidPackages];\r\n const bidPackageToUpdate = copy.find((v) => v.id === bidValue.bidPackageId);\r\n\r\n if (bidPackageToUpdate) {\r\n const matchingBidTotalIndex = bidPackageToUpdate.bidTotals.findIndex(\r\n (v) =>\r\n normalizeNullOrUndefined(v.bidderId) ===\r\n normalizeNullOrUndefined(bidValue.bidderId) &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(bidValue.alternateId),\r\n );\r\n\r\n let bidTotalToUpdate: BidPackageBidTotal;\r\n\r\n // NOTE: The total is a combination of the bids totals and the adjustment, so we want to update the adjustment\r\n // to get to the total we want\r\n if (matchingBidTotalIndex > -1) {\r\n const originalBidTotal = bidPackageToUpdate.bidTotals[matchingBidTotalIndex];\r\n\r\n const newAdjustmentAmount = (bidValue.value ?? 0) - (originalBidTotal.bidsTotal ?? 0);\r\n\r\n bidTotalToUpdate = new BidPackageBidTotal({\r\n ...bidPackageToUpdate.bidTotals[matchingBidTotalIndex],\r\n adjustmentAmount: newAdjustmentAmount,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n });\r\n\r\n bidPackageToUpdate.bidTotals[matchingBidTotalIndex] = bidTotalToUpdate;\r\n } else {\r\n bidTotalToUpdate = new BidPackageBidTotal({\r\n bidderId: bidValue.bidderId,\r\n alternateId: bidValue.alternateId,\r\n bidPackageId: bidValue.bidPackageId,\r\n adjustmentAmount: bidValue.value,\r\n bidsTotal: 0,\r\n isDirty: true, // Set the isDirty flag so this persists through any SignalR data updates\r\n });\r\n\r\n bidPackageToUpdate.bidTotals.push(bidTotalToUpdate);\r\n }\r\n\r\n return copy;\r\n }\r\n\r\n return currBidPackages;\r\n};\r\n\r\nconst onBlurCallback_BidAmount = (\r\n originalBidPackages: BidPackage[],\r\n currentBidPackages: BidPackage[],\r\n alternates: Alternate[],\r\n bidValue: BidAmountValue,\r\n): ICommand | null => {\r\n const originalBidPackage = originalBidPackages.find((v) => v.id === bidValue.bidPackageId);\r\n const updatedBidPackage = currentBidPackages.find((v) => v.id === bidValue.bidPackageId);\r\n\r\n if (!originalBidPackage || !updatedBidPackage) {\r\n return null;\r\n }\r\n\r\n let shouldSetAdjustment = false;\r\n\r\n const originalBidTotal = originalBidPackage.bidTotals.find(\r\n (v) =>\r\n normalizeNullOrUndefined(v.bidderId) ===\r\n normalizeNullOrUndefined(bidValue.bidderId) &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(bidValue.alternateId),\r\n );\r\n\r\n const newBidTotal = updatedBidPackage.bidTotals.find(\r\n (v) =>\r\n normalizeNullOrUndefined(v.bidderId) ===\r\n normalizeNullOrUndefined(bidValue.bidderId) &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(bidValue.alternateId),\r\n );\r\n\r\n // If the bid total didn't exist in the original but it does now or the adjustment amounts are different,\r\n // we should set an adjustment\r\n if (!originalBidTotal && newBidTotal) {\r\n shouldSetAdjustment = true;\r\n } else if (\r\n // NOTE: Even though we don't actually use the adjustment amount on the command,\r\n // we can still check if it changed in this code\r\n originalBidTotal &&\r\n newBidTotal &&\r\n originalBidTotal.adjustmentAmount !== newBidTotal.adjustmentAmount\r\n ) {\r\n shouldSetAdjustment = true;\r\n }\r\n\r\n if (shouldSetAdjustment) {\r\n // NOTE: We should have the selected bidder entity and can get the company name from it\r\n const matchingBidder = updatedBidPackage.selectedBidder;\r\n if (!matchingBidder) {\r\n return null;\r\n }\r\n\r\n const matchingAlternate = alternates.find((v) => v.id === bidValue.alternateId);\r\n\r\n // NOTE: We do not set the value of the adjustment but instead set the bid amount parameter on the command\r\n return new SetAdjustmentOnBidPackageCommand(\r\n bidValue.bidPackageId,\r\n matchingBidder.companyName!,\r\n matchingAlternate?.name || null,\r\n null,\r\n bidValue.value ?? 0,\r\n );\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst onChangeCallback_Contingency = (\r\n currBidPackages: BidPackage[],\r\n bidPackageContingencyAmount: BidPackageContingencyValue,\r\n): BidPackage[] => {\r\n const copy = [...currBidPackages];\r\n const bidPackageToUpdateIndex = copy.findIndex(\r\n (v) => v.id === bidPackageContingencyAmount.bidPackageId,\r\n );\r\n\r\n if (bidPackageToUpdateIndex > -1) {\r\n const bidPackageToUpdate = clone(copy[bidPackageToUpdateIndex]);\r\n bidPackageToUpdate.contingencyPercentage = bidPackageContingencyAmount.value ?? 0;\r\n copy[bidPackageToUpdateIndex] = bidPackageToUpdate;\r\n\r\n return copy;\r\n }\r\n\r\n return currBidPackages;\r\n};\r\n\r\nconst onBlurCallback_Contingency = (\r\n originalBidPackages: BidPackage[],\r\n currentBidPackages: BidPackage[],\r\n bidPackageContingencyAmount: BidPackageContingencyValue,\r\n): ICommand | null => {\r\n const originalBidPackage = originalBidPackages.find(\r\n (v) => v.id === bidPackageContingencyAmount.bidPackageId,\r\n );\r\n const updatedBidPackage = currentBidPackages.find(\r\n (v) => v.id === bidPackageContingencyAmount.bidPackageId,\r\n );\r\n\r\n if (!originalBidPackage || !updatedBidPackage) {\r\n return null;\r\n }\r\n\r\n // We just need to check that the contingency percentage actually changed.\r\n // NOTE: The contingency percentage should not be nullable.\r\n if (\r\n (originalBidPackage.contingencyPercentage ?? 0) !==\r\n (updatedBidPackage.contingencyPercentage ?? 0)\r\n ) {\r\n return new SetContingencyOnBidPackageCommand(\r\n bidPackageContingencyAmount.bidPackageId,\r\n bidPackageContingencyAmount.value,\r\n );\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst successFunction_BidAmount = (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackagesToUpdate: BidPackage[],\r\n bidPackagesWithUpdatedData: BidPackage[],\r\n): BidPackage[] => {\r\n // Add or update the adjustment\r\n if (command instanceof SetAdjustmentOnBidPackageCommand) {\r\n try {\r\n const copy = [...bidPackagesToUpdate];\r\n\r\n const indexOfBidPackageToUpdate = copy.findIndex((v) => v.id === command.bidPackageId);\r\n if (indexOfBidPackageToUpdate === -1) {\r\n throw new Error();\r\n }\r\n\r\n const bidPackage_Source = bidPackagesWithUpdatedData.find(\r\n (v) => v.id === command.bidPackageId,\r\n );\r\n if (!bidPackage_Source) {\r\n throw new Error();\r\n }\r\n\r\n const bidPackageToUpdate = clone(copy[indexOfBidPackageToUpdate]);\r\n copy[indexOfBidPackageToUpdate] = bidPackageToUpdate;\r\n\r\n // NOTE: The selected bidder on the bid package has the info we need\r\n // and will be the bidder this code applies to\r\n const selectedBidder = bidPackageToUpdate.selectedBidder;\r\n if (\r\n !selectedBidder ||\r\n !areTrimmedStringsEqual(selectedBidder.companyName, command.companyName)\r\n ) {\r\n throw new Error();\r\n }\r\n\r\n let alternate: Alternate | null = null;\r\n\r\n // If the alternate name is present on the command, we have to find the matching alternate\r\n if (command.alternateName) {\r\n alternate =\r\n alternates.find((v) => areTrimmedStringsEqual(v.name || '', command.alternateName)) ??\r\n null;\r\n\r\n if (!alternate) {\r\n throw new Error();\r\n }\r\n }\r\n\r\n const indexOfBidTotalToUpdateFrom = bidPackage_Source.bidTotals.find(\r\n (v) =>\r\n normalizeNullOrUndefined(v.bidderId) ===\r\n normalizeNullOrUndefined(selectedBidder.id) &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternate?.id),\r\n );\r\n\r\n // We should always have a bid total to update from\r\n if (!indexOfBidTotalToUpdateFrom) {\r\n throw new Error();\r\n }\r\n\r\n const indexOfBidTotalToUpdate = bidPackageToUpdate.bidTotals.findIndex(\r\n (v) =>\r\n normalizeNullOrUndefined(v.bidderId) ===\r\n normalizeNullOrUndefined(selectedBidder.id) &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternate?.id),\r\n );\r\n\r\n if (indexOfBidTotalToUpdate > -1) {\r\n bidPackageToUpdate.bidTotals[indexOfBidTotalToUpdate] = clone(indexOfBidTotalToUpdateFrom);\r\n } else {\r\n bidPackageToUpdate.bidTotals.push(clone(indexOfBidTotalToUpdateFrom));\r\n }\r\n\r\n return copy;\r\n } catch {\r\n return bidPackagesToUpdate;\r\n }\r\n }\r\n\r\n return bidPackagesToUpdate;\r\n};\r\n\r\nconst errorFunction_BidAmount = (\r\n command: ICommand,\r\n alternates: Alternate[],\r\n bidPackagesToUpdate: BidPackage[],\r\n bidPackagesWithUpdatedData: BidPackage[],\r\n): BidPackage[] => {\r\n if (command instanceof SetAdjustmentOnBidPackageCommand) {\r\n try {\r\n const copy = [...bidPackagesToUpdate];\r\n\r\n // Restore the bid total\r\n const bidPackage_Target_Index = copy.findIndex((v) => v.id === command.bidPackageId);\r\n if (bidPackage_Target_Index === -1) {\r\n throw new Error();\r\n }\r\n\r\n const bidPackageToUpdate = clone(copy[bidPackage_Target_Index]);\r\n copy[bidPackage_Target_Index] = bidPackageToUpdate;\r\n\r\n const bidPackage_Source = bidPackagesWithUpdatedData.find(\r\n (v) => v.id === command.bidPackageId,\r\n );\r\n\r\n if (!bidPackageToUpdate || !bidPackage_Source) {\r\n throw new Error();\r\n }\r\n\r\n // NOTE: The selected bidder on the bid package has the info we need\r\n // and will be the bidder this code applies to\r\n const selectedBidder = bidPackageToUpdate.selectedBidder;\r\n if (\r\n !selectedBidder ||\r\n !areTrimmedStringsEqual(selectedBidder.companyName, command.companyName)\r\n ) {\r\n throw new Error();\r\n }\r\n\r\n let alternate: Alternate | null = null;\r\n\r\n // If the alternate name is present on the command, we have to find the matching alternate\r\n if (command.alternateName) {\r\n alternate =\r\n alternates.find((v) => areTrimmedStringsEqual(v.name || '', command.alternateName)) ??\r\n null;\r\n\r\n if (!alternate) {\r\n throw new Error();\r\n }\r\n }\r\n\r\n const matchingBidTotalFromBidPackageTargetIndex = bidPackageToUpdate.bidTotals.findIndex(\r\n (v) =>\r\n normalizeNullOrUndefined(v.bidderId) ===\r\n normalizeNullOrUndefined(selectedBidder.id) &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternate?.id),\r\n );\r\n\r\n // The bid total should exist because it was either added or updated\r\n if (matchingBidTotalFromBidPackageTargetIndex === -1) {\r\n throw new Error();\r\n }\r\n\r\n const matchingBidTotalFromBidPackageSource = bidPackage_Source.bidTotals.find(\r\n (v) =>\r\n normalizeNullOrUndefined(v.bidderId) ===\r\n normalizeNullOrUndefined(selectedBidder.id) &&\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(alternate?.id),\r\n );\r\n\r\n bidPackageToUpdate.bidTotals = [...bidPackageToUpdate.bidTotals];\r\n\r\n // If the bid total didn't exist in the source bid package, we want to remove it from the target one\r\n if (!matchingBidTotalFromBidPackageSource) {\r\n bidPackageToUpdate.bidTotals.splice(matchingBidTotalFromBidPackageTargetIndex, 1);\r\n } else {\r\n bidPackageToUpdate.bidTotals[matchingBidTotalFromBidPackageTargetIndex] = clone(\r\n matchingBidTotalFromBidPackageSource,\r\n );\r\n }\r\n\r\n return copy;\r\n } catch {\r\n return bidPackagesToUpdate;\r\n }\r\n }\r\n\r\n return [];\r\n};\r\n\r\nconst successFunction_Contingency = (\r\n command: ICommand,\r\n bidPackagesToUpdate: BidPackage[],\r\n bidPackagesWithUpdatedData: BidPackage[],\r\n): BidPackage[] => {\r\n // Add or update the contingency\r\n if (command instanceof SetContingencyOnBidPackageCommand) {\r\n try {\r\n const copy = [...bidPackagesToUpdate];\r\n\r\n const indexOfBidPackageToUpdate = copy.findIndex((v) => v.id === command.bidPackageId);\r\n const bidPackage_Source = bidPackagesWithUpdatedData.find(\r\n (v) => v.id === command.bidPackageId,\r\n );\r\n\r\n if (indexOfBidPackageToUpdate === -1 || !bidPackage_Source) {\r\n throw new Error();\r\n }\r\n\r\n const bidPackageToUpdate = clone(copy[indexOfBidPackageToUpdate]);\r\n bidPackageToUpdate.contingencyPercentage = bidPackage_Source.contingencyPercentage;\r\n copy[indexOfBidPackageToUpdate] = bidPackageToUpdate;\r\n\r\n return copy;\r\n } catch {\r\n return bidPackagesToUpdate;\r\n }\r\n }\r\n\r\n return bidPackagesToUpdate;\r\n};\r\n\r\nconst errorFunction_Contingency = (\r\n command: ICommand,\r\n bidPackagesToUpdate: BidPackage[],\r\n bidPackagesWithUpdatedData: BidPackage[],\r\n): BidPackage[] => {\r\n // Add or update the contingency\r\n if (command instanceof SetContingencyOnBidPackageCommand) {\r\n try {\r\n const copy = [...bidPackagesToUpdate];\r\n\r\n const indexOfBidPackageToUpdate = copy.findIndex((v) => v.id === command.bidPackageId);\r\n const bidPackage_Source = bidPackagesWithUpdatedData.find(\r\n (v) => v.id === command.bidPackageId,\r\n );\r\n\r\n if (indexOfBidPackageToUpdate === -1 || !bidPackage_Source) {\r\n throw new Error();\r\n }\r\n\r\n const bidPackageToUpdate = clone(copy[indexOfBidPackageToUpdate]);\r\n bidPackageToUpdate.contingencyPercentage = bidPackage_Source.contingencyPercentage;\r\n copy[indexOfBidPackageToUpdate] = bidPackageToUpdate;\r\n\r\n return copy;\r\n } catch {\r\n return bidPackagesToUpdate;\r\n }\r\n }\r\n\r\n return bidPackagesToUpdate;\r\n};\r\n\r\nexport default useBidSummary;\r\n","import { Switch, SwitchProps } from '@progress/kendo-react-inputs';\r\nimport React, { useState } from 'react';\r\nimport { generateUuid } from '../../../utils/uuid';\r\nimport './BTSwitch.scss';\r\n\r\ninterface Props {\r\n label: string;\r\n title?: string;\r\n}\r\n\r\n// A very basic wrapped Kendo input element that we can use independently of Formik\r\nconst BTSwitch: React.ForwardRefRenderFunction = (\r\n { id, name, label, title, checked, ...rest },\r\n ref,\r\n) => {\r\n const [inputIdentifier] = useState(id || name || label || generateUuid());\r\n\r\n return (\r\n // Fall back to using the label for the input name\r\n
    \r\n {label ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n {/* NOTE: The \"checked\" property drives this input, not \"value\" */}\r\n {\r\n if (e) {\r\n if (ref) {\r\n (ref as React.MutableRefObject).current = e;\r\n }\r\n\r\n if (inputIdentifier && e.element && !e.element.getAttribute('data-testid')) {\r\n e.element.setAttribute('data-testid', inputIdentifier);\r\n }\r\n }\r\n }}\r\n name={inputIdentifier}\r\n id={inputIdentifier}\r\n checked={checked}\r\n {...rest}\r\n />\r\n
    \r\n );\r\n};\r\n\r\nexport default React.forwardRef(BTSwitch);\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Alternate } from '../../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport GeneralConstants from '../../../../../../constants/general';\r\nimport {\r\n generateEmptyGridRowWithEmptyCells_Base,\r\n generateEmptyGridRow_Base,\r\n} from '../../../../../../utils/btgrid';\r\nimport {\r\n convertBigToNumber,\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n} from '../../../../../../utils/general';\r\nimport BTNumericInput from '../../../../../common-page-components/inputs/BTNumericInput';\r\nimport BTSwitch from '../../../../../common-page-components/inputs/BTSwitch';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport { BidSummaryOptions } from '../../BidSummaryPage';\r\nimport useBidSummaryPageContext from '../../BidSummaryPageContext';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_BidPackage_Alternate_SubGrid: (\r\n isReadOnly: boolean,\r\n testId: string,\r\n alternate: Alternate,\r\n bidPackages: BidPackage[],\r\n frozenBidPackageIds: string[],\r\n frozenBidPackageAdjustmentNoteIds: string[],\r\n ) => BTSubGrid;\r\n}\r\n\r\ninterface Props {\r\n bidSummaryOptions: BidSummaryOptions;\r\n}\r\n\r\nconst useBidSummary_BidPackage_Alternate = ({ bidSummaryOptions }: Props): ReturnValue => {\r\n const { t } = useTranslation();\r\n const { alternate_Change, bidAmount_Blur, bidAmount_Change } = useBidSummaryPageContext();\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const generateBidSummary_BidPackage_Alternate_SubGrid = useCallback(\r\n (\r\n isReadOnly: boolean,\r\n testId: string,\r\n alternate: Alternate,\r\n bidPackages: BidPackage[],\r\n frozenBidPackageIds: string[],\r\n frozenBidPackageAdjustmentNoteIds: string[],\r\n ): BTSubGrid => {\r\n const headerRow = generateEmptyGridRow_Base(\r\n `${alternate.name} - 725b07dd-1a6f-4e14-a0d2-b6a75d842e80`,\r\n );\r\n\r\n headerRow.cells.push({\r\n testId: 'AlternateHeaderCell',\r\n cellContent: <>,\r\n cellWidth: bidSummaryOptions.displayClassifications ? 'xl' : 'md',\r\n cellHorizontalAlignment: 'center',\r\n cellAdditionalStyles: [\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n 'border-sides',\r\n 'border-top',\r\n ],\r\n });\r\n\r\n if (isReadOnly) {\r\n headerRow.cells[0].cellContent = (\r\n
    \r\n
    \r\n {alternate.name}\r\n
    \r\n\r\n \r\n \r\n \r\n
    \r\n );\r\n } else {\r\n headerRow.cells[0].cellContent = (\r\n \r\n {\r\n alternate_Change({\r\n alternateName: alternate.name!,\r\n value: !alternate.enabled,\r\n });\r\n }}\r\n />\r\n
    \r\n {alternate.name}\r\n
    \r\n \r\n );\r\n }\r\n\r\n headerRow.showBottomBorder = true;\r\n headerRow.bottomBorderColor = 'black';\r\n\r\n const contentRows = generateEmptyGridRowWithEmptyCells_Base(\r\n `${alternate.name} - d43c223a-8a2e-406c-bede-09e6332a48ad`,\r\n 1,\r\n 'md',\r\n );\r\n contentRows.showBottomBorder = true;\r\n contentRows.bottomBorderColor = 'black';\r\n\r\n contentRows.cells[0].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n contentRows.cells[0].cellHorizontalAlignment = 'right';\r\n contentRows.cells[0].cellAdditionalStyles = ['border-left'];\r\n\r\n if (bidSummaryOptions.displayClassifications) {\r\n contentRows.cells.push({\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: 'md',\r\n cellBackgroundColor: 'green',\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-sides'],\r\n });\r\n } else {\r\n contentRows.cells[0].cellAdditionalStyles = ['border-sides'];\r\n }\r\n\r\n // Add data rows\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n let totalForAllBidPackages = new Big(0);\r\n let totalAdjustmentAmountsForAllBidPackages = new Big(0);\r\n\r\n bidPackages.forEach((currBidPackage) => {\r\n let bidTotal: { total: Big; adjustmentAmount: Big } | null;\r\n if (currBidPackage.isGeneralCondition) {\r\n // For the general conditions bid package, the bid total is the base estimate amount\r\n bidTotal = {\r\n total: new Big(currBidPackage.getBaseEstimateAmount(alternate.id!)?.total ?? 0),\r\n adjustmentAmount: new Big(0),\r\n };\r\n } else {\r\n bidTotal = currBidPackage.selectedBidderId\r\n ? currBidPackage.getBaseBidAmountInfoForBidder(\r\n currBidPackage.selectedBidderId,\r\n alternate.id!,\r\n )\r\n : null;\r\n }\r\n\r\n if (bidTotal) {\r\n totalForAllBidPackages = totalForAllBidPackages.add(new Big(bidTotal.total ?? 0));\r\n\r\n totalAdjustmentAmountsForAllBidPackages = totalAdjustmentAmountsForAllBidPackages.add(\r\n new Big(bidTotal.adjustmentAmount ?? 0),\r\n );\r\n }\r\n\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(\r\n `${alternate.id} - ${currBidPackage.id}`,\r\n bidSummaryOptions.displayClassifications ? 2 : 1,\r\n 'md',\r\n );\r\n\r\n newDataRow.isHoverable = true;\r\n newDataRow.showBottomBorder = true;\r\n const newDataRowTotalCell = newDataRow.cells[0];\r\n const bigZero = new Big(0);\r\n const bidTotalAdjustmentOrZero = bidTotal?.adjustmentAmount || bigZero;\r\n const bidTotalTotalOrZero = bidTotal?.total || bigZero;\r\n const bidTotalContainsAdjustments = bidTotalAdjustmentOrZero.cmp(bigZero) !== 0;\r\n\r\n newDataRowTotalCell.cellTriggersBTPopover = true;\r\n newDataRowTotalCell.onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: bidTotalContainsAdjustments\r\n ? `${t('bid-summary:containsAdjustmentText')} ${formatNumberAsCurrencyFull(\r\n bidTotalAdjustmentOrZero,\r\n )}`\r\n : '',\r\n title: formatNumberAsCurrencyFull(bidTotalTotalOrZero),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRowTotalCell.onCellMouseLeave = (e) => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n\r\n newDataRowTotalCell.cellAdditionalStyles = ['border-left'];\r\n newDataRowTotalCell.cellHorizontalAlignment = 'right';\r\n\r\n const bidPackageIsFrozen = frozenBidPackageIds.includes(currBidPackage.id);\r\n\r\n // NOTE: When a bid package adjustment note is frozen, we cannot set a bid amount because that creates an adjustment\r\n // on the server and appends text to an adjustment note\r\n const bidPackageAdjustmentNotesAreFrozen = frozenBidPackageAdjustmentNoteIds.includes(\r\n currBidPackage.adjustments.find((v) => v.alternateId === alternate.id)?.notesId || '',\r\n );\r\n\r\n newDataRowTotalCell.cellContent = (\r\n
    \r\n {/* If there no selected bidder for a bid package, we want to make this read only,\r\n since we set an adjustment on the selected bidder under the hood when the user changes a bid amount */}\r\n {isReadOnly ||\r\n bidPackageIsFrozen ||\r\n bidPackageAdjustmentNotesAreFrozen ||\r\n !currBidPackage.selectedBidderId ||\r\n currBidPackage.isGeneralCondition ? (\r\n
    {formatNumberAsCurrency(bidTotalTotalOrZero)}
    \r\n ) : (\r\n {\r\n const newValue = inputElement.target.value || 0;\r\n\r\n bidAmount_Blur({\r\n bidderId: currBidPackage.selectedBidderId || '',\r\n value: newValue,\r\n alternateId: alternate.id,\r\n bidPackageId: currBidPackage.id,\r\n });\r\n }}\r\n onChange={(inputElement) => {\r\n const newValue = inputElement.target.value || 0;\r\n\r\n bidAmount_Change({\r\n bidderId: currBidPackage.selectedBidderId || '',\r\n value: newValue,\r\n alternateId: alternate.id,\r\n bidPackageId: currBidPackage.id,\r\n });\r\n }}\r\n />\r\n )}\r\n
    \r\n );\r\n\r\n // We set a custom background color if there is an adjustment amount for the bid total\r\n if (bidTotalContainsAdjustments) {\r\n newDataRowTotalCell.cellBackgroundColor = 'light-green';\r\n }\r\n\r\n if (!bidSummaryOptions.displayClassifications) {\r\n newDataRowTotalCell.cellAdditionalStyles.push('border-right');\r\n } else {\r\n const newDataRowAdjustmentCell = newDataRow.cells[1];\r\n\r\n newDataRowAdjustmentCell.cellTriggersBTPopover = true;\r\n newDataRowAdjustmentCell.onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(bidTotalAdjustmentOrZero),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRowAdjustmentCell.onCellMouseLeave = (e) => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n newDataRowAdjustmentCell.cellContent = (\r\n
    {formatNumberAsCurrency(bidTotalAdjustmentOrZero)}
    \r\n );\r\n newDataRowAdjustmentCell.cellHorizontalAlignment = 'right';\r\n newDataRowAdjustmentCell.cellBackgroundColor = 'green';\r\n newDataRowAdjustmentCell.cellAdditionalStyles = ['border-sides'];\r\n }\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Add a row for the 'subtotal'\r\n const subtotalRow = generateEmptyGridRowWithEmptyCells_Base(\r\n `${alternate.name} - 8717627c-cd92-42f9-b341-06626f0e2378`,\r\n bidSummaryOptions.displayClassifications ? 2 : 1,\r\n 'md',\r\n ) as BTGridRowPrimary;\r\n\r\n subtotalRow.isHoverable = true;\r\n\r\n const subtotalRowTotalCell = subtotalRow.cells[0];\r\n const subtotalRowAdjustmentCell = subtotalRow.cells[1];\r\n\r\n const bigZero = new Big(0);\r\n const formattedZero = formatNumberAsCurrencyFull(bigZero);\r\n const formattedTotalForAllBidPackages = formatNumberAsCurrencyFull(totalForAllBidPackages);\r\n const formattedTotalForAllAdjustments = formatNumberAsCurrencyFull(\r\n totalAdjustmentAmountsForAllBidPackages,\r\n );\r\n const totalContainsAdjustments = totalAdjustmentAmountsForAllBidPackages.cmp(bigZero) !== 0;\r\n\r\n subtotalRowTotalCell.cellTriggersBTPopover = true;\r\n subtotalRowTotalCell.onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: alternate.enabled\r\n ? totalContainsAdjustments\r\n ? `${t('bid-summary:totalContainsAdjustmentText')} ${formattedTotalForAllAdjustments}`\r\n : ''\r\n : `${t('bid-summary:alternateNotEnabledButContainsValue', {\r\n total: formattedTotalForAllBidPackages,\r\n })}`,\r\n title: alternate.enabled ? formattedTotalForAllBidPackages : formattedZero,\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n subtotalRowTotalCell.onCellMouseLeave = (e) => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n subtotalRowTotalCell.cellContent = alternate.enabled ? (\r\n
    {formatNumberAsCurrency(totalForAllBidPackages)}
    \r\n ) : (\r\n
    {formatNumberAsCurrency(0)}
    \r\n );\r\n subtotalRowTotalCell.cellHorizontalAlignment = 'right';\r\n\r\n // We set a custom background color if there is an adjustment amount for the bid total\r\n if (totalContainsAdjustments) {\r\n subtotalRowTotalCell.cellBackgroundColor = 'light-green';\r\n }\r\n\r\n if (!bidSummaryOptions.displayClassifications) {\r\n subtotalRowTotalCell.cellAdditionalStyles = [\r\n 'border-sides',\r\n 'border-bottom',\r\n 'border-rounded-bottom-left',\r\n 'border-rounded-bottom-right',\r\n ];\r\n } else {\r\n subtotalRowTotalCell.cellAdditionalStyles = [\r\n 'border-left',\r\n 'border-bottom',\r\n 'border-rounded-bottom-left',\r\n ];\r\n\r\n subtotalRowAdjustmentCell.cellTriggersBTPopover = true;\r\n subtotalRowAdjustmentCell.onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text:\r\n !alternate.enabled && totalContainsAdjustments\r\n ? `${t('bid-summary:alternateNotEnabledAdjustmentsTotal', {\r\n total: formattedTotalForAllAdjustments,\r\n })}`\r\n : '',\r\n title: alternate.enabled ? formattedTotalForAllAdjustments : formattedZero,\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n subtotalRowAdjustmentCell.onCellMouseLeave = (e) => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n subtotalRowAdjustmentCell.cellContent = alternate.enabled ? (\r\n
    {formatNumberAsCurrency(totalAdjustmentAmountsForAllBidPackages)}
    \r\n ) : (\r\n
    {formatNumberAsCurrency(0)}
    \r\n );\r\n subtotalRowAdjustmentCell.cellHorizontalAlignment = 'right';\r\n subtotalRowAdjustmentCell.cellBackgroundColor = 'green';\r\n subtotalRowAdjustmentCell.cellAdditionalStyles = [\r\n 'border-right',\r\n 'border-sides',\r\n 'border-bottom',\r\n 'border-rounded-bottom-right',\r\n ];\r\n\r\n if (!alternate.enabled) {\r\n subtotalRowTotalCell.cellBackgroundColor = 'light-gray';\r\n subtotalRowAdjustmentCell.cellBackgroundColor = 'light-gray';\r\n }\r\n }\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [contentRows, ...dataRows, subtotalRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [\r\n bidSummaryOptions.displayClassifications,\r\n t,\r\n alternate_Change,\r\n setDisplayedPopoverInfo,\r\n bidAmount_Blur,\r\n bidAmount_Change,\r\n ],\r\n );\r\n\r\n return { generateBidSummary_BidPackage_Alternate_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_BidPackage_Alternate;\r\n","import Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { Project } from '../../../../../../classes/odata/project';\r\nimport GeneralConstants from '../../../../../../constants/general';\r\nimport {\r\n generateEmptyGridRowWithEmptyCells_Base,\r\n generateEmptyGridRow_Base,\r\n} from '../../../../../../utils/btgrid';\r\nimport {\r\n convertBigToNumber,\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n} from '../../../../../../utils/general';\r\nimport BTNumericInput from '../../../../../common-page-components/inputs/BTNumericInput';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport useBidSummaryPageContext from '../../BidSummaryPageContext';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_BidPackage_BidAmount_SubGrid: (\r\n isReadOnly: boolean,\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n frozenBidPackageIds: string[],\r\n frozenBidPackageAdjustmentNoteIds: string[],\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_BidPackage_BidAmount = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const { bidAmount_Blur, bidAmount_Change } = useBidSummaryPageContext();\r\n\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const generateBidSummary_BidPackage_BidAmount_SubGrid = useCallback(\r\n (\r\n isReadOnly: boolean,\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n frozenBidPackageIds: string[],\r\n frozenBidPackageAdjustmentNoteIds: string[],\r\n ): BTSubGrid => {\r\n // Add an empty row\r\n const emptyRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'b1dc8907-9ad9-4d4f-bd51-f68927e0f4e1',\r\n 1,\r\n 'fill',\r\n );\r\n\r\n // Add a column headers row\r\n const headerRow = generateEmptyGridRow_Base('7fc0e37a-b0ad-4ea7-8c67-d6ffb0c44dc9');\r\n headerRow.showBottomBorder = true;\r\n headerRow.bottomBorderColor = 'black';\r\n\r\n headerRow.cells.push({\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: 'sm',\r\n cellHorizontalAlignment: 'right',\r\n });\r\n\r\n // Add data rows\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n let totalAdjustments = new Big(0);\r\n\r\n bidPackages.forEach((currBidPackage) => {\r\n const newRow = generateEmptyGridRow_Base(`Bid Amount Row - ${currBidPackage.id}`);\r\n newRow.showBottomBorder = true;\r\n newRow.isHoverable = true;\r\n\r\n let currBidTotal: { total: Big; adjustmentAmount: Big } | null;\r\n if (currBidPackage.isGeneralCondition) {\r\n // For the general conditions bid package, the bid total is the base estimate amount\r\n currBidTotal = {\r\n total: new Big(currBidPackage.getBaseEstimateAmount(null)?.total ?? 0),\r\n adjustmentAmount: new Big(0),\r\n };\r\n } else {\r\n currBidTotal = currBidPackage.selectedBidderId\r\n ? currBidPackage.getBaseBidAmountInfoForBidder(currBidPackage.selectedBidderId, null)\r\n : null;\r\n }\r\n\r\n const bidPackageIsFrozen = frozenBidPackageIds.includes(currBidPackage.id);\r\n\r\n // NOTE: When a bid package adjustment note is frozen, we cannot set a bid amount because that creates an adjustment\r\n // on the server and appends text to an adjustment note\r\n const bidPackageAdjustmentNotesAreFrozen = frozenBidPackageAdjustmentNoteIds.includes(\r\n currBidPackage.adjustments.find((v) => !v.alternateId)?.notesId || '',\r\n );\r\n\r\n const currBidTotalOrZero = currBidTotal?.total || new Big(0);\r\n const currBidAdjustmentAmountOrZero = currBidTotal?.adjustmentAmount || new Big(0);\r\n totalAdjustments = totalAdjustments.add(currBidAdjustmentAmountOrZero);\r\n\r\n const adjustmentAmountAsNumber = currBidAdjustmentAmountOrZero.toNumber();\r\n const containsAdjustments = adjustmentAmountAsNumber !== 0;\r\n\r\n newRow.cells = [\r\n {\r\n cellTriggersBTPopover: true,\r\n onCellMouseEnter: (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: containsAdjustments\r\n ? `${t('bid-summary:containsAdjustmentText')} ${formatNumberAsCurrency(\r\n currBidAdjustmentAmountOrZero,\r\n )}`\r\n : '',\r\n title: formatNumberAsCurrencyFull(currBidTotalOrZero),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n },\r\n onCellMouseLeave: () => {\r\n setDisplayedPopoverInfo(null);\r\n },\r\n cellContent: (\r\n
    \r\n {/* If there no selected bidder for a bid package, we want to make this read only, \r\n since we set an adjustment on the selected bidder under the hood when the user changes a bid amount */}\r\n {isReadOnly ||\r\n bidPackageAdjustmentNotesAreFrozen ||\r\n bidPackageIsFrozen ||\r\n !currBidPackage.selectedBidderId ||\r\n currBidPackage.isGeneralCondition ? (\r\n //Display a rounded (2-decimal) value, but display the full 5-decimal value on hover\r\n
    {formatNumberAsCurrency(currBidTotalOrZero)}
    \r\n ) : (\r\n \r\n {\r\n const newValue = inputElement.target.value || 0;\r\n\r\n bidAmount_Blur({\r\n bidderId: currBidPackage.selectedBidderId || '',\r\n bidPackageId: currBidPackage.id,\r\n value: newValue,\r\n alternateId: undefined,\r\n });\r\n }}\r\n onChange={(inputElement) => {\r\n const newValue = inputElement.target.value || 0;\r\n\r\n bidAmount_Change({\r\n bidderId: currBidPackage.selectedBidderId || '',\r\n bidPackageId: currBidPackage.id,\r\n value: newValue,\r\n alternateId: undefined,\r\n });\r\n }}\r\n />\r\n
    \r\n )}\r\n \r\n ),\r\n cellWidth: 'fill',\r\n cellHorizontalAlignment: 'right',\r\n cellBackgroundColor:\r\n // We set a custom background color if there is an adjustment amount for the bid total\r\n containsAdjustments ? 'light-green' : undefined,\r\n },\r\n ];\r\n\r\n dataRows.push(newRow);\r\n });\r\n\r\n // Add a row for the 'subtotal'\r\n const subtotalRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '631128ac-f09d-4afa-a57c-d39d5c2681d8',\r\n 1,\r\n 'fill',\r\n ) as BTGridRowPrimary;\r\n\r\n subtotalRow.isHoverable = true;\r\n\r\n const calculatedBaseEstimateAmount = Project.calculateBaseEstimateAmount(bidPackages);\r\n const subtotalRowTotalCell = subtotalRow.cells[0];\r\n const containsAdjustments = totalAdjustments.cmp(0) !== 0;\r\n\r\n subtotalRowTotalCell.cellTriggersBTPopover = true;\r\n subtotalRowTotalCell.onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: containsAdjustments\r\n ? `${t('bid-summary:totalContainsAdjustmentText')} ${formatNumberAsCurrency(\r\n totalAdjustments,\r\n )}`\r\n : '',\r\n title: formatNumberAsCurrencyFull(calculatedBaseEstimateAmount),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n subtotalRowTotalCell.onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n subtotalRowTotalCell.cellContent = (\r\n
    {formatNumberAsCurrency(calculatedBaseEstimateAmount)}
    \r\n );\r\n subtotalRowTotalCell.cellHorizontalAlignment = 'right';\r\n\r\n if (containsAdjustments) {\r\n subtotalRowTotalCell.cellBackgroundColor = 'light-green';\r\n subtotalRowTotalCell.cellAdditionalStyles = [\r\n 'border-rounded-bottom-left',\r\n 'border-rounded-bottom-right',\r\n ];\r\n }\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [emptyRow],\r\n rows: [headerRow, ...dataRows, subtotalRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [bidAmount_Blur, bidAmount_Change, setDisplayedPopoverInfo, t],\r\n );\r\n\r\n return {\r\n generateBidSummary_BidPackage_BidAmount_SubGrid,\r\n };\r\n};\r\n\r\nexport default useBidSummary_BidPackage_BidAmount;\r\n","import React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Link } from 'react-router-dom';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport ApplicationRoutes from '../../../../../../constants/routes';\r\nimport {\r\n generateEmptyGridRowWithEmptyCells_Base,\r\n generateEmptyGridRowWithEmptyCells_Primary,\r\n generateEmptyGridRow_Primary,\r\n} from '../../../../../../utils/btgrid';\r\nimport { getEmailWithoutDomain } from '../../../../../../utils/strings';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport { BidSummaryOptions } from '../../BidSummaryPage';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_BidPackage_BidPackages_SubGrid: (\r\n testId: string,\r\n bidSummaryOptions: BidSummaryOptions,\r\n bidPackages: BidPackage[],\r\n ) => BTSubGrid;\r\n}\r\n\r\n// Generates a BTSubGrid that contains the bid packages\r\nconst useBidSummary_BidPackage_BidPackages = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const generateBidSummary_BidPackage_BidPackages_SubGrid = useCallback(\r\n (\r\n testId: string,\r\n bidSummaryOptions: BidSummaryOptions,\r\n bidPackages: BidPackage[],\r\n ): BTSubGrid => {\r\n const cellWidths: BTGridCellWidths[] = ['lg', 'sm', 'md'];\r\n\r\n // Add an empty row\r\n const emptyRow = generateEmptyGridRowWithEmptyCells_Primary(\r\n '6123f750-7814-4bcf-a9ab-82cb6a32352f',\r\n 3,\r\n cellWidths[0],\r\n );\r\n emptyRow.cells[1].cellWidth = cellWidths[1];\r\n emptyRow.cells[2].cellWidth = cellWidths[2];\r\n\r\n if (!bidSummaryOptions.displayAssignedToColumn) {\r\n emptyRow.cells = emptyRow.cells.slice(0, emptyRow.cells.length - 1);\r\n }\r\n\r\n // Add a column headers row\r\n const columnHeadersRow = generateEmptyGridRow_Primary('d0ae0e07-acb0-4d41-918b-95f570a48e89');\r\n columnHeadersRow.showBottomBorder = true;\r\n columnHeadersRow.bottomBorderColor = 'black';\r\n\r\n columnHeadersRow.cells = [\r\n {\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: cellWidths[0],\r\n frozenOnHorizontalScroll: true,\r\n },\r\n {\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: cellWidths[1],\r\n },\r\n ];\r\n\r\n if (bidSummaryOptions.displayAssignedToColumn) {\r\n columnHeadersRow.cells.push({\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: cellWidths[2],\r\n });\r\n }\r\n\r\n // Add data rows\r\n const dataRows: BTGridRowPrimary[] = [];\r\n\r\n bidPackages.forEach((currBidPackage) => {\r\n const newRow = generateEmptyGridRow_Primary(currBidPackage.id!) as BTGridRowPrimary;\r\n newRow.isHoverable = true;\r\n\r\n newRow.showBottomBorder = true;\r\n\r\n const bidPackageDescriptionValue = `${currBidPackage.code} - ${currBidPackage.description}`;\r\n newRow.cells = [\r\n {\r\n cellContent: (\r\n // NOTE: The nested divs are important here, for the cell content overflow CSS to work correctly\r\n <>\r\n
    \r\n \r\n {bidPackageDescriptionValue}\r\n \r\n
    \r\n {/* TODO - this needs to be wired up to conditionally show */}\r\n {/*
    \r\n \r\n
    */}\r\n \r\n ),\r\n cellTriggersBTPopover: true,\r\n onCellMouseEnter: (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: bidPackageDescriptionValue,\r\n title: '',\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n },\r\n onCellMouseLeave: () => {\r\n setDisplayedPopoverInfo(null);\r\n },\r\n cellWidth: cellWidths[0],\r\n frozenOnHorizontalScroll: true,\r\n trimTextOnOverflow: true,\r\n },\r\n {\r\n cellContent: currBidPackage.isGeneralCondition ? (\r\n <>\r\n ) : (\r\n
    {currBidPackage.selectedBidder?.companyName || t('general:none')}
    \r\n ),\r\n cellWidth: cellWidths[1],\r\n },\r\n ];\r\n\r\n if (bidSummaryOptions.displayAssignedToColumn) {\r\n const assignedToUserName = currBidPackage.assignedToUser?.name ?? '';\r\n const emailWithoutDomain = getEmailWithoutDomain(\r\n currBidPackage.assignedToUser?.email ?? '',\r\n );\r\n\r\n const tooltipText = assignedToUserName ? emailWithoutDomain : '';\r\n\r\n newRow.cells.push({\r\n cellContent: (\r\n // NOTE: The nested divs are important here, for the cell content overflow CSS to work correctly\r\n
    \r\n
    {assignedToUserName || emailWithoutDomain || t('general:none')}
    \r\n
    \r\n ),\r\n cellTriggersBTPopover: tooltipText ? true : false,\r\n onCellMouseEnter: (e) => {\r\n if (tooltipText) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: tooltipText,\r\n title: '',\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n },\r\n onCellMouseLeave: () => {\r\n if (tooltipText) {\r\n setDisplayedPopoverInfo(null);\r\n }\r\n },\r\n cellWidth: cellWidths[2],\r\n trimTextOnOverflow: true,\r\n });\r\n }\r\n\r\n dataRows.push(newRow);\r\n });\r\n\r\n // Add a row for the 'subtotal'\r\n const subtotalRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '9e63b034-ebf4-41ef-b56d-b389042359ab',\r\n 1,\r\n 'fill',\r\n ) as BTGridRowPrimary;\r\n\r\n subtotalRow.isHoverable = true;\r\n\r\n subtotalRow.cells[0].cellContent = (\r\n
    \r\n

    {t('general:subtotal')}

    \r\n
    \r\n );\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [emptyRow],\r\n rows: [columnHeadersRow, ...dataRows, subtotalRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [setDisplayedPopoverInfo, t],\r\n );\r\n\r\n return {\r\n generateBidSummary_BidPackage_BidPackages_SubGrid,\r\n };\r\n};\r\n\r\nexport default useBidSummary_BidPackage_BidPackages;\r\n","import Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport {\r\n generateEmptyGridRowWithEmptyCells_Base,\r\n generateEmptyGridRow_Base,\r\n} from '../../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n} from '../../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport { BidClassificationTypes } from '../../../../../enums/bid-package-enums';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_BidPackage_Classification_SubGrid: (\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst getCellBackgroundColorForClassification = (\r\n classificationType: number,\r\n): BTGridCellBackgroundColors => {\r\n switch (classificationType) {\r\n case BidClassificationTypes.Adjustment:\r\n return 'green';\r\n\r\n case BidClassificationTypes.GeneralRequirement:\r\n return 'orange';\r\n\r\n case BidClassificationTypes.OwnerAllow:\r\n return 'yellow';\r\n\r\n case BidClassificationTypes.Unallocated:\r\n return 'light-gray';\r\n\r\n case BidClassificationTypes.Risk:\r\n return 'manly-salmon';\r\n\r\n case BidClassificationTypes.MissingScope:\r\n return 'light-blue';\r\n\r\n case BidClassificationTypes.SubBid:\r\n return 'gray';\r\n\r\n case BidClassificationTypes.Totals:\r\n return 'dark-blue';\r\n\r\n default:\r\n throw new Error(`Unsupported classification type: '${classificationType}'.`);\r\n }\r\n};\r\n\r\n// Generates the grid section containing bid package classifications\r\nconst useBidSummary_BidPackage_Classification = (): ReturnValue => {\r\n // TODO - this will eventually come into this component via props\r\n // const [classificationCollections] = useState(\r\n // stubClassificationsData,\r\n // );\r\n\r\n const { t } = useTranslation();\r\n\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const generateBidSummary_BidPackage_Classification_SubGrid = useCallback(\r\n (testId: string, bidPackages: BidPackage[]): BTSubGrid => {\r\n // Add a header row\r\n const headerRow = generateEmptyGridRow_Base('610804e2-439a-4d82-89ac-f8e1632ecc49');\r\n // headerRow.showBottomBorder = true;\r\n\r\n headerRow.cells.push({\r\n cellContent:
    Classification
    ,\r\n cellWidth: 'fill',\r\n cellHorizontalAlignment: 'center',\r\n cellBackgroundColor: 'light-gray',\r\n cellAdditionalStyles: [\r\n 'border-sides',\r\n 'border-top',\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n ],\r\n });\r\n headerRow.showBottomBorder = true;\r\n headerRow.bottomBorderColor = 'black';\r\n\r\n // Add a row for column headers\r\n const columnHeaderRow = generateEmptyGridRow_Base('c7488fac-acef-46a4-98fc-32bcad18b862');\r\n columnHeaderRow.showBottomBorder = true;\r\n columnHeaderRow.bottomBorderColor = 'black';\r\n\r\n columnHeaderRow.cells = [\r\n {\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: 'sm',\r\n cellBackgroundColor: getCellBackgroundColorForClassification(\r\n BidClassificationTypes.SubBid,\r\n ),\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-left'],\r\n },\r\n {\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: 'sm',\r\n cellBackgroundColor: getCellBackgroundColorForClassification(\r\n BidClassificationTypes.MissingScope,\r\n ),\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-left'],\r\n },\r\n {\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: 'sm',\r\n cellBackgroundColor: getCellBackgroundColorForClassification(BidClassificationTypes.Risk),\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-left'],\r\n },\r\n {\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: 'sm',\r\n cellBackgroundColor: getCellBackgroundColorForClassification(\r\n BidClassificationTypes.OwnerAllow,\r\n ),\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-left'],\r\n },\r\n {\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: 'sm',\r\n cellBackgroundColor: getCellBackgroundColorForClassification(\r\n BidClassificationTypes.GeneralRequirement,\r\n ),\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-left'],\r\n },\r\n {\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: 'sm',\r\n cellBackgroundColor: getCellBackgroundColorForClassification(\r\n BidClassificationTypes.Unallocated,\r\n ),\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-left'],\r\n },\r\n {\r\n cellContent: (\r\n
    \r\n \r\n
    \r\n ),\r\n cellWidth: 'sm',\r\n cellBackgroundColor: getCellBackgroundColorForClassification(\r\n BidClassificationTypes.Adjustment,\r\n ),\r\n cellHorizontalAlignment: 'right',\r\n cellAdditionalStyles: ['border-sides'],\r\n },\r\n ];\r\n\r\n const classificationTypes = [\r\n BidClassificationTypes.SubBid,\r\n BidClassificationTypes.MissingScope,\r\n BidClassificationTypes.Risk,\r\n BidClassificationTypes.OwnerAllow,\r\n BidClassificationTypes.GeneralRequirement,\r\n BidClassificationTypes.Unallocated,\r\n BidClassificationTypes.Adjustment,\r\n ];\r\n\r\n const classificationSubtotals: Dictionary = {};\r\n classificationTypes.forEach((v) => {\r\n classificationSubtotals[v] = new Big(0);\r\n });\r\n\r\n // Add data rows\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n bidPackages.forEach((currBidPackage) => {\r\n const newRow = generateEmptyGridRow_Base(currBidPackage.id);\r\n newRow.showBottomBorder = true;\r\n\r\n classificationTypes.forEach((currClassificationType) => {\r\n let valueForClassification = new Big(0);\r\n\r\n // An adjustment amount is not a classification, so we pull it from another entity\r\n if (currClassificationType === BidClassificationTypes.Adjustment) {\r\n if (currBidPackage.selectedBidderId) {\r\n const bidTotalForSelectedBidder = currBidPackage.bidTotals.find(\r\n (v) => v.bidderId === currBidPackage.selectedBidderId && !v.alternateId,\r\n );\r\n\r\n valueForClassification = new Big(bidTotalForSelectedBidder?.adjustmentAmount || 0);\r\n }\r\n } else {\r\n valueForClassification = new Big(\r\n currBidPackage.selectedBidderId\r\n ? currBidPackage.getBidTotalForClassification(\r\n currBidPackage.selectedBidderId,\r\n currClassificationType,\r\n )\r\n : 0,\r\n );\r\n }\r\n\r\n classificationSubtotals[currClassificationType] = classificationSubtotals[\r\n currClassificationType\r\n ].add(valueForClassification || 0);\r\n\r\n const newCell: BTGridCell = {\r\n cellTriggersBTPopover: true,\r\n onCellMouseEnter: (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(valueForClassification),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n },\r\n onCellMouseLeave: () => {\r\n setDisplayedPopoverInfo(null);\r\n },\r\n cellContent:
    {formatNumberAsCurrency(valueForClassification || 0)}
    ,\r\n cellWidth: 'sm',\r\n cellBackgroundColor: getCellBackgroundColorForClassification(currClassificationType),\r\n cellHorizontalAlignment: 'right',\r\n };\r\n\r\n if (newRow.cells.length === classificationTypes.length - 1) {\r\n newCell.cellAdditionalStyles = ['border-sides'];\r\n } else {\r\n newCell.cellAdditionalStyles = ['border-left'];\r\n }\r\n\r\n newRow.cells.push(newCell);\r\n });\r\n\r\n dataRows.push(newRow);\r\n });\r\n\r\n // Add a row for the 'subtotal'\r\n const subtotalRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '86f03897-2899-4c9f-a280-3d0c47815beb',\r\n classificationTypes.length,\r\n 'sm',\r\n ) as BTGridRowPrimary;\r\n\r\n classificationTypes.forEach((currClassificationType, i) => {\r\n const currSubtotalRowCell = subtotalRow.cells[i];\r\n\r\n currSubtotalRowCell.cellContent = (\r\n
    {formatNumberAsCurrency(classificationSubtotals[currClassificationType])}
    \r\n );\r\n currSubtotalRowCell.cellBackgroundColor = getCellBackgroundColorForClassification(\r\n currClassificationType,\r\n );\r\n currSubtotalRowCell.cellHorizontalAlignment = 'right';\r\n currSubtotalRowCell.cellAdditionalStyles = ['border-bottom', 'border-left'];\r\n\r\n if (i === 0) {\r\n currSubtotalRowCell.cellAdditionalStyles!.push('border-rounded-bottom-left');\r\n } else if (i === classificationTypes.length - 1) {\r\n currSubtotalRowCell.cellAdditionalStyles!.push(\r\n 'border-right',\r\n 'border-rounded-bottom-right',\r\n );\r\n }\r\n currSubtotalRowCell.cellTriggersBTPopover = true;\r\n currSubtotalRowCell.onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(classificationSubtotals[currClassificationType]),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n currSubtotalRowCell.onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n });\r\n\r\n dataRows.push(subtotalRow);\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [columnHeaderRow, ...dataRows],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [setDisplayedPopoverInfo, t],\r\n );\r\n\r\n return {\r\n generateBidSummary_BidPackage_Classification_SubGrid,\r\n };\r\n};\r\n\r\nexport default useBidSummary_BidPackage_Classification;\r\n","import Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport GeneralConstants from '../../../../../../constants/general';\r\nimport {\r\n generateEmptyGridRowWithEmptyCells_Base,\r\n generateEmptyGridRow_Base,\r\n} from '../../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n formatNumberAsDecimal,\r\n} from '../../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_BidPackage_ComparisonToBaseEstimate_SubGrid: (\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_BidPackage_ComparisonToBaseEstimate = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const generateBidSummary_BidPackage_ComparisonToBaseEstimate_SubGrid = useCallback(\r\n (testId: string, bidPackages: BidPackage[]): BTSubGrid => {\r\n const headerRow = generateEmptyGridRow_Base('0fc2ad09-8952-4608-932c-2f14d00bc5f1');\r\n headerRow.cells.push({\r\n cellContent: (\r\n
    \r\n {t('bid-summary:comparisonToBaseEstimate')}\r\n
    \r\n ),\r\n cellWidth: 'fill',\r\n cellHorizontalAlignment: 'center',\r\n cellAdditionalStyles: [\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n 'border-sides',\r\n 'border-top',\r\n ],\r\n });\r\n headerRow.showBottomBorder = true;\r\n headerRow.bottomBorderColor = 'black';\r\n\r\n const contentRows = generateEmptyGridRowWithEmptyCells_Base(\r\n 'fd0d6eb2-0fa1-4bc9-97eb-40380b6e802a',\r\n 3,\r\n 'sm',\r\n );\r\n contentRows.showBottomBorder = true;\r\n contentRows.bottomBorderColor = 'black';\r\n\r\n contentRows.cells[0].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n contentRows.cells[0].cellAdditionalStyles = ['border-left'];\r\n contentRows.cells[0].cellHorizontalAlignment = 'right';\r\n contentRows.cells[0].cellAdditionalStyles = ['border-left'];\r\n\r\n contentRows.cells[1].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n contentRows.cells[1].cellHorizontalAlignment = 'right';\r\n\r\n contentRows.cells[2].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n contentRows.cells[2].cellHorizontalAlignment = 'right';\r\n contentRows.cells[2].cellAdditionalStyles = ['border-right'];\r\n contentRows.cells[2].cellHorizontalAlignment = 'right';\r\n\r\n // Add data rows\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n let totalAmountForAllBidPackages = new Big(0);\r\n let totalVarianceForAllBidPackages = new Big(0);\r\n\r\n bidPackages.forEach((currBidPackage) => {\r\n const baseEstimateAmount = new Big(currBidPackage.getBaseEstimateAmount(null)?.total || 0);\r\n\r\n const selectedBidderBidTotal = new Big(\r\n (currBidPackage.selectedBidderId\r\n ? currBidPackage.getBaseBidAmountInfoForBidder(currBidPackage.selectedBidderId, null)\r\n : null\r\n )?.total || 0,\r\n );\r\n\r\n const variance = currBidPackage.calculateVariance(\r\n baseEstimateAmount,\r\n selectedBidderBidTotal,\r\n );\r\n\r\n const variancePercentage = currBidPackage.calculateVariancePercentage(\r\n baseEstimateAmount,\r\n selectedBidderBidTotal,\r\n );\r\n\r\n // Do not include totals for general condition bid packages\r\n if (!currBidPackage.isGeneralCondition) {\r\n totalAmountForAllBidPackages = totalAmountForAllBidPackages.add(baseEstimateAmount);\r\n totalVarianceForAllBidPackages = totalVarianceForAllBidPackages.add(variance);\r\n }\r\n\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currBidPackage.id, 3, 'sm');\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.isHoverable = true;\r\n\r\n newDataRow.cells[0].cellAdditionalStyles = ['border-left'];\r\n newDataRow.cells[0].cellHorizontalAlignment = 'right';\r\n newDataRow.cells[1].cellHorizontalAlignment = 'right';\r\n newDataRow.cells[2].cellAdditionalStyles = ['border-right'];\r\n newDataRow.cells[2].cellHorizontalAlignment = 'right';\r\n\r\n if (currBidPackage.isGeneralCondition || !currBidPackage.selectedBidderId) {\r\n newDataRow.cells[0].cellContent = <>;\r\n newDataRow.cells[1].cellContent = <>;\r\n newDataRow.cells[2].cellContent = <>;\r\n } else {\r\n const comparisonAmount =\r\n currBidPackage.selectedBidderId && !selectedBidderBidTotal.eq(0)\r\n ? baseEstimateAmount\r\n : 0;\r\n newDataRow.cells[0].cellTriggersBTPopover = true;\r\n newDataRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(comparisonAmount),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n\r\n newDataRow.cells[0].cellContent =
    {formatNumberAsCurrency(comparisonAmount)}
    ;\r\n\r\n if (!currBidPackage.selectedBidderId || selectedBidderBidTotal.eq(0)) {\r\n newDataRow.cells[1].cellContent = <>;\r\n newDataRow.cells[2].cellContent = <>;\r\n } else {\r\n newDataRow.cells[1].cellTriggersBTPopover = true;\r\n newDataRow.cells[1].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(variance),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRow.cells[1].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n newDataRow.cells[1].cellContent =
    {formatNumberAsCurrency(variance)}
    ;\r\n if (!variancePercentage.eq(0)) {\r\n newDataRow.cells[2].cellTriggersBTPopover = true;\r\n newDataRow.cells[2].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: `${formatNumberAsDecimal(\r\n variancePercentage\r\n .round(\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MAXIMUM_FRACTION_DIGITS,\r\n GeneralConstants.ROUNDING_MODE.TRUNCATE,\r\n )\r\n .toNumber(),\r\n )}%`,\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRow.cells[2].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n newDataRow.cells[2].cellContent = (\r\n
    {`${formatNumberAsDecimal(\r\n variancePercentage\r\n .round(\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MINIMUM_FRACTION_DIGITS,\r\n GeneralConstants.ROUNDING_MODE.ROUND_HALF_UP,\r\n )\r\n .toNumber(),\r\n )}%`}
    \r\n );\r\n } else {\r\n newDataRow.cells[2].cellContent = <>;\r\n }\r\n }\r\n }\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Add a row for the 'subtotal'\r\n const subtotalRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '41af2e9b-f8b9-40d8-aa2c-3a4a2cdd127d',\r\n 3,\r\n 'sm',\r\n ) as BTGridRowPrimary;\r\n\r\n subtotalRow.isHoverable = true;\r\n\r\n subtotalRow.cells[0].cellTriggersBTPopover = true;\r\n subtotalRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(totalAmountForAllBidPackages),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n subtotalRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n subtotalRow.cells[0].cellContent = (\r\n
    {formatNumberAsCurrency(totalAmountForAllBidPackages)}
    \r\n );\r\n subtotalRow.cells[0].cellHorizontalAlignment = 'right';\r\n subtotalRow.cells[0].cellAdditionalStyles = [\r\n 'border-left',\r\n 'border-bottom',\r\n 'border-rounded-bottom-left',\r\n ];\r\n\r\n subtotalRow.cells[1].cellTriggersBTPopover = true;\r\n subtotalRow.cells[1].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(totalVarianceForAllBidPackages),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n subtotalRow.cells[1].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n subtotalRow.cells[1].cellContent = (\r\n
    {formatNumberAsCurrency(totalVarianceForAllBidPackages)}
    \r\n );\r\n subtotalRow.cells[1].cellHorizontalAlignment = 'right';\r\n subtotalRow.cells[1].cellAdditionalStyles = ['border-bottom'];\r\n\r\n subtotalRow.cells[2].cellContent = <>;\r\n subtotalRow.cells[2].cellAdditionalStyles = [\r\n 'border-right',\r\n 'border-bottom',\r\n 'border-rounded-bottom-right',\r\n ];\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [contentRows, ...dataRows, subtotalRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [setDisplayedPopoverInfo, t],\r\n );\r\n\r\n return { generateBidSummary_BidPackage_ComparisonToBaseEstimate_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_BidPackage_ComparisonToBaseEstimate;\r\n","import Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport GeneralConstants from '../../../../../../constants/general';\r\nimport { generateEmptyGridRowWithEmptyCells_Base } from '../../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n formatNumberAsPercentage,\r\n} from '../../../../../../utils/general';\r\nimport BTNumericInput from '../../../../../common-page-components/inputs/BTNumericInput';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport useBidSummaryPageContext from '../../BidSummaryPageContext';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_BidPackage_Contingencies_SubGrid: (\r\n isReadOnly: boolean,\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n frozenBidPackageIds: string[],\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_BidPackage_Contingencies = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n const { contingency_Blur, contingency_Change } = useBidSummaryPageContext();\r\n\r\n const generateBidSummary_BidPackage_Contingencies_SubGrid = useCallback(\r\n (\r\n isReadOnly: boolean,\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n frozenBidPackageIds: string[],\r\n ): BTSubGrid => {\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'c2613c94-66ee-4d08-9954-97b024976caf',\r\n 1,\r\n 'fill',\r\n );\r\n\r\n const contentRows = generateEmptyGridRowWithEmptyCells_Base(\r\n '9ddc28f7-8590-49f6-a6cd-413632b0cd21',\r\n 2,\r\n 'sm',\r\n );\r\n contentRows.showBottomBorder = true;\r\n contentRows.bottomBorderColor = 'black';\r\n\r\n contentRows.cells[0].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n contentRows.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n contentRows.cells[1].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n contentRows.cells[1].cellHorizontalAlignment = 'right';\r\n\r\n // Add data rows\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n let totalContingencyAmount = new Big(0);\r\n\r\n bidPackages.forEach((currBidPackage) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currBidPackage.id, 2, 'sm');\r\n\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.isHoverable = true;\r\n\r\n const contingencyPercentageCell = newDataRow.cells[0];\r\n contingencyPercentageCell.cellHorizontalAlignment = 'right';\r\n\r\n const bidPackageIsFrozen = frozenBidPackageIds.includes(currBidPackage.id);\r\n const formattedcontingencyPercentage = formatNumberAsPercentage(\r\n new Big(currBidPackage.contingencyPercentage ?? 0).div(100),\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MINIMUM_FRACTION_DIGITS,\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MAXIMUM_FRACTION_DIGITS,\r\n );\r\n\r\n if (isReadOnly || bidPackageIsFrozen) {\r\n contingencyPercentageCell.cellContent =
    {formattedcontingencyPercentage}
    ;\r\n } else {\r\n contingencyPercentageCell.cellContent = (\r\n
    \r\n {\r\n const newValue = inputElement.target.value || 0;\r\n\r\n contingency_Blur({\r\n bidPackageId: currBidPackage.id,\r\n value: newValue,\r\n });\r\n }}\r\n onChange={(inputElement) => {\r\n const newValue = inputElement.target.value || 0;\r\n\r\n contingency_Change({\r\n bidPackageId: currBidPackage.id,\r\n value: newValue,\r\n });\r\n }}\r\n />\r\n
    \r\n );\r\n }\r\n\r\n contingencyPercentageCell.cellTriggersBTPopover = true;\r\n contingencyPercentageCell.onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formattedcontingencyPercentage,\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n contingencyPercentageCell.onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n\r\n const contingencyAmount = currBidPackage.contingencyAmount?.contingencyAmount ?? 0;\r\n totalContingencyAmount = totalContingencyAmount.add(contingencyAmount);\r\n const contingencyAmountCell = newDataRow.cells[1];\r\n\r\n contingencyAmountCell.cellTriggersBTPopover = true;\r\n contingencyAmountCell.onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(contingencyAmount),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n contingencyAmountCell.onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n contingencyAmountCell.cellContent =
    {formatNumberAsCurrency(contingencyAmount)}
    ;\r\n contingencyAmountCell.cellHorizontalAlignment = 'right';\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Add a row for the 'subtotal'\r\n const subtotalRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'e139512c-25b9-47c9-9956-26b6f43a0d37',\r\n 2,\r\n 'sm',\r\n ) as BTGridRowPrimary;\r\n\r\n subtotalRow.isHoverable = true;\r\n\r\n subtotalRow.cells[1].cellTriggersBTPopover = true;\r\n subtotalRow.cells[1].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(totalContingencyAmount),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n subtotalRow.cells[1].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n subtotalRow.cells[1].cellContent = (\r\n
    {formatNumberAsCurrency(totalContingencyAmount)}
    \r\n );\r\n subtotalRow.cells[1].cellHorizontalAlignment = 'right';\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [contentRows, ...dataRows, subtotalRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [contingency_Blur, contingency_Change, setDisplayedPopoverInfo, t],\r\n );\r\n\r\n return { generateBidSummary_BidPackage_Contingencies_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_BidPackage_Contingencies;\r\n","import React, { useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { generateEmptyGridRowWithEmptyCells_Base } from '../../../../../../utils/btgrid';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_BidPackage_Notes_SubGrid: (\r\n isReadOnly: boolean,\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_BidPackage_Notes = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const generateBidSummary_BidPackage_Notes_SubGrid = useCallback(\r\n (isReadOnly: boolean, testId: string, bidPackages: BidPackage[]): BTSubGrid => {\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '1a11ea1c-5496-452c-8bf4-4c288acf5aff',\r\n 1,\r\n 'lg',\r\n );\r\n\r\n const contentRows = generateEmptyGridRowWithEmptyCells_Base(\r\n 'ba1f9a2b-1df7-4fbc-9411-91f2241327bc',\r\n 1,\r\n 'lg',\r\n );\r\n contentRows.showBottomBorder = true;\r\n contentRows.bottomBorderColor = 'black';\r\n\r\n contentRows.cells[0].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n\r\n // Add data rows\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n bidPackages.forEach((currBidPackage) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currBidPackage.id, 1, 'lg');\r\n\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.isHoverable = true;\r\n\r\n if (isReadOnly) {\r\n newDataRow.cells[0].cellContent = (\r\n
    {currBidPackage.notes || `(${t('general:noNotes')})`}
    \r\n );\r\n } else {\r\n newDataRow.cells[0].cellContent =
    {currBidPackage.notes || ''}
    ;\r\n }\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Add a row for the 'subtotal'\r\n const subtotalRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'bde4ca0c-513d-424c-828a-ca7982c7a001',\r\n 1,\r\n 'fill',\r\n ) as BTGridRowPrimary;\r\n\r\n subtotalRow.isHoverable = true;\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [contentRows, ...dataRows, subtotalRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [t],\r\n );\r\n\r\n return { generateBidSummary_BidPackage_Notes_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_BidPackage_Notes;\r\n","import Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { Bidder } from '../../../../../../classes/odata/bidder';\r\nimport GeneralConstants from '../../../../../../constants/general';\r\nimport {\r\n generateEmptyGridRowWithEmptyCells_Base,\r\n generateEmptyGridRow_Base,\r\n} from '../../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n} from '../../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\n\r\ntype BidderTotal = { bidder: Bidder; total: Big };\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_BidPackage_SecondBidderAnalysis_SubGrid: (\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_BidPackage_SecondBidderAnalysis = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n const getSecondBidderAndTotal = useCallback(\r\n (currBidPackage: BidPackage, bidderTotals: BidderTotal[]): BidderTotal | null => {\r\n // Get the second bidder by order\r\n const secondBidder = currBidPackage.bidders.find((b) => b.isSecondBidder());\r\n\r\n // If there is no selected bidder or second bidder, return null\r\n if (!currBidPackage.selectedBidderId || !secondBidder) {\r\n return null;\r\n }\r\n\r\n return {\r\n bidder: secondBidder,\r\n total: currBidPackage.getBaseBidAmountInfoForBidder(secondBidder.id!, null).total,\r\n };\r\n },\r\n [],\r\n );\r\n\r\n const generateBidSummary_BidPackage_SecondBidderAnalysis_SubGrid = useCallback(\r\n (testId: string, bidPackages: BidPackage[]): BTSubGrid => {\r\n const headerRow = generateEmptyGridRow_Base('2a378bfd-abac-4837-83c8-c5b2c4bac1bc');\r\n headerRow.cells.push({\r\n cellContent: (\r\n
    \r\n {t('bid-summary:secondBidderAnalysis')}\r\n
    \r\n ),\r\n cellWidth: 'fill',\r\n cellHorizontalAlignment: 'center',\r\n cellAdditionalStyles: [\r\n 'border-rounded-top-left',\r\n 'border-rounded-top-right',\r\n 'border-sides',\r\n 'border-top',\r\n ],\r\n });\r\n headerRow.showBottomBorder = true;\r\n headerRow.bottomBorderColor = 'black';\r\n\r\n const contentRows = generateEmptyGridRowWithEmptyCells_Base(\r\n '1af77a37-be5b-43bb-af68-5a4304914e25',\r\n 3,\r\n 'sm',\r\n );\r\n contentRows.showBottomBorder = true;\r\n contentRows.bottomBorderColor = 'black';\r\n\r\n contentRows.cells[0].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n contentRows.cells[0].cellAdditionalStyles = ['border-left'];\r\n contentRows.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n contentRows.cells[1].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n\r\n contentRows.cells[2].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n contentRows.cells[2].cellHorizontalAlignment = 'right';\r\n contentRows.cells[2].cellAdditionalStyles = ['border-right'];\r\n contentRows.cells[2].cellHorizontalAlignment = 'right';\r\n\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n let totalForAllBidPackages = new Big(0);\r\n\r\n bidPackages.forEach((currBidPackage) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(\r\n currBidPackage.id || '03d5eb86-8e9a-4dd5-89dc-05c0ee953b2a',\r\n 3,\r\n 'sm',\r\n );\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.isHoverable = true;\r\n\r\n newDataRow.cells[0].cellAdditionalStyles = ['border-left'];\r\n newDataRow.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n newDataRow.cells[2].cellAdditionalStyles = ['border-right'];\r\n newDataRow.cells[2].cellHorizontalAlignment = 'right';\r\n\r\n const selectedBidderTotal = currBidPackage.selectedBidderId\r\n ? currBidPackage.getBaseBidAmountInfoForBidder(currBidPackage.selectedBidderId, null)\r\n ?.total\r\n : new Big(0);\r\n\r\n const bidderTotals: BidderTotal[] = !currBidPackage.selectedBidderId\r\n ? []\r\n : currBidPackage.bidders\r\n .map((bidder) => {\r\n return {\r\n bidder: bidder,\r\n total:\r\n currBidPackage.getBaseBidAmountInfoForBidder(bidder.id!, null)?.total ||\r\n new Big(0),\r\n };\r\n })\r\n .filter((v) => v.bidder.id !== currBidPackage.selectedBidderId && v.total > Big(0));\r\n\r\n const secondBidderInfo = getSecondBidderAndTotal(currBidPackage, bidderTotals);\r\n\r\n totalForAllBidPackages = totalForAllBidPackages.add(secondBidderInfo?.total || new Big(0));\r\n\r\n // Secondary Bid\r\n if (currBidPackage.isGeneralCondition || !currBidPackage.selectedBidderId) {\r\n newDataRow.cells[0].cellContent = <>;\r\n } else {\r\n const secondaryBidValue = secondBidderInfo?.total;\r\n newDataRow.cells[0].cellTriggersBTPopover = true;\r\n newDataRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: secondaryBidValue ? formatNumberAsCurrencyFull(secondaryBidValue) : '',\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n newDataRow.cells[0].cellContent = (\r\n
    {secondaryBidValue ? formatNumberAsCurrency(secondaryBidValue) : ''}
    \r\n );\r\n }\r\n\r\n // Secondary Bid Variance\r\n if (!currBidPackage.selectedBidderId) {\r\n // We have no selected bidder - render nothing\r\n newDataRow.cells[1].cellContent = <>;\r\n } else if (secondBidderInfo?.bidder) {\r\n // We have secondary bids\r\n newDataRow.cells[1].cellContent =
    {secondBidderInfo.bidder.companyName}
    ;\r\n } else {\r\n // We have no secondary bidders - render nothing\r\n newDataRow.cells[1].cellContent = <>;\r\n }\r\n\r\n // Secondary Bid Variance Percentage\r\n if (bidderTotals.length > 0) {\r\n const variancePercentage = secondBidderInfo\r\n ? currBidPackage.calculateVariancePercentage(\r\n secondBidderInfo.total,\r\n selectedBidderTotal,\r\n )\r\n : new Big(0);\r\n\r\n if (!variancePercentage.eq(0)) {\r\n newDataRow.cells[2].cellTriggersBTPopover = true;\r\n newDataRow.cells[2].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: `${variancePercentage.round(\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MAXIMUM_FRACTION_DIGITS,\r\n GeneralConstants.ROUNDING_MODE.TRUNCATE,\r\n )}%`,\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRow.cells[2].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n newDataRow.cells[2].cellContent = (\r\n
    {`${variancePercentage.round(\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MINIMUM_FRACTION_DIGITS,\r\n GeneralConstants.ROUNDING_MODE.ROUND_HALF_UP,\r\n )}%`}
    \r\n );\r\n } else {\r\n newDataRow.cells[2].cellContent = <>;\r\n }\r\n } else {\r\n // We have no secondary bids - render nothing\r\n newDataRow.cells[2].cellContent = <>;\r\n }\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Add a row for the 'subtotal'\r\n const subtotalRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '8c4d3536-d830-4de9-b9f5-f7827d946f40',\r\n 3,\r\n 'sm',\r\n ) as BTGridRowPrimary;\r\n\r\n subtotalRow.isHoverable = true;\r\n\r\n subtotalRow.cells[0].cellTriggersBTPopover = true;\r\n subtotalRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(totalForAllBidPackages),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n subtotalRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n subtotalRow.cells[0].cellContent = (\r\n
    {formatNumberAsCurrency(totalForAllBidPackages)}
    \r\n );\r\n subtotalRow.cells[0].cellHorizontalAlignment = 'right';\r\n subtotalRow.cells[0].cellAdditionalStyles = [\r\n 'border-left',\r\n 'border-bottom',\r\n 'border-rounded-bottom-left',\r\n ];\r\n\r\n subtotalRow.cells[1].cellContent = <>;\r\n subtotalRow.cells[1].cellAdditionalStyles = ['border-bottom'];\r\n\r\n subtotalRow.cells[2].cellContent = <>;\r\n subtotalRow.cells[2].cellAdditionalStyles = [\r\n 'border-right',\r\n 'border-bottom',\r\n 'border-rounded-bottom-right',\r\n ];\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [contentRows, ...dataRows, subtotalRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [getSecondBidderAndTotal, setDisplayedPopoverInfo, t],\r\n );\r\n\r\n return {\r\n generateBidSummary_BidPackage_SecondBidderAnalysis_SubGrid,\r\n };\r\n};\r\n\r\nexport default useBidSummary_BidPackage_SecondBidderAnalysis;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Alternate } from '../../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport {\r\n MeasurementSystemDisplayNames,\r\n MeasurementSystemValues,\r\n} from '../../../../../../constants/preferences/measurement-systems';\r\nimport { generateEmptyGridRowWithEmptyCells_Base } from '../../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n} from '../../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport useBidSummaryPageContext from '../../BidSummaryPageContext';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_BidPackage_Totals_SubGrid: (\r\n isReadOnly: boolean,\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n alternates: Alternate[],\r\n projectPreferences: Preferences,\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_BidPackage_Totals = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n const { project_EditBiddersRanges } = useBidSummaryPageContext();\r\n\r\n const generateBidSummary_BidPackage_Totals_SubGrid = useCallback(\r\n (\r\n isReadOnly: boolean,\r\n testId: string,\r\n bidPackages: BidPackage[],\r\n alternates: Alternate[],\r\n projectPreferences: Preferences,\r\n ): BTSubGrid => {\r\n // Give it default values if it doesn't exist\r\n projectPreferences = projectPreferences || {\r\n measurementSystem: {\r\n id: MeasurementSystemValues.Imperial,\r\n name: MeasurementSystemDisplayNames.Imperial,\r\n },\r\n lowBiddersMax: 1,\r\n midBiddersMax: 3,\r\n };\r\n\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '87acba12-94b2-4ed8-aed7-a233d7147b0a',\r\n 1,\r\n 'fill',\r\n );\r\n\r\n const contentRows = generateEmptyGridRowWithEmptyCells_Base(\r\n 'fef2cea4-662a-49db-9e8a-33c7296f1d89',\r\n 2,\r\n 'sm',\r\n );\r\n contentRows.showBottomBorder = true;\r\n contentRows.bottomBorderColor = 'black';\r\n\r\n contentRows.cells[0].cellContent = (\r\n
    \r\n \r\n
    \r\n );\r\n contentRows.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n contentRows.cells[1].cellWidth = 'sm';\r\n contentRows.cells[1].cellContent = (\r\n
    \r\n \r\n\r\n {isReadOnly ? (\r\n <>\r\n ) : (\r\n \r\n project_EditBiddersRanges({\r\n lowBiddersMax: projectPreferences.lowBiddersMax,\r\n midBiddersMax: projectPreferences.midBiddersMax,\r\n })\r\n }\r\n >\r\n \r\n \r\n )}\r\n
    \r\n );\r\n contentRows.cells[1].cellHorizontalAlignment = 'right';\r\n\r\n // Add data rows\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n const getCellBackgroundColor = (numberOfBids: number): string => {\r\n if (numberOfBids <= projectPreferences.lowBiddersMax) {\r\n return 'backgroundColor-red';\r\n }\r\n\r\n if (\r\n numberOfBids > projectPreferences.lowBiddersMax &&\r\n numberOfBids <= projectPreferences.midBiddersMax\r\n ) {\r\n return 'backgroundColor-yellow';\r\n }\r\n\r\n return 'backgroundColor-green';\r\n };\r\n\r\n const getNumberOfBidsColor = (numberOfBids: number): 'red' | 'yellow' | 'green' => {\r\n if (numberOfBids <= projectPreferences.lowBiddersMax) {\r\n return 'red';\r\n }\r\n\r\n if (\r\n numberOfBids > projectPreferences.lowBiddersMax &&\r\n numberOfBids <= projectPreferences.midBiddersMax\r\n ) {\r\n return 'yellow';\r\n }\r\n\r\n return 'green';\r\n };\r\n\r\n let subtotalForAllTotals = new Big(0);\r\n\r\n bidPackages.forEach((currBidPackage) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currBidPackage.id, 2, 'sm');\r\n newDataRow.isHoverable = true;\r\n\r\n const currBidPackageTotal = currBidPackage.calculateBidTotal(alternates);\r\n\r\n subtotalForAllTotals = subtotalForAllTotals.add(currBidPackageTotal);\r\n\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.cells[0].cellTriggersBTPopover = true;\r\n newDataRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(currBidPackageTotal),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n newDataRow.cells[0].cellContent =
    {formatNumberAsCurrency(currBidPackageTotal)}
    ;\r\n newDataRow.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.cells[1].cellHorizontalAlignment = 'right';\r\n newDataRow.cells[1].cellContent = currBidPackage.isGeneralCondition ? (\r\n <>\r\n ) : (\r\n \r\n {currBidPackage.bidders.length}\r\n \r\n );\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Add a row for the 'subtotal'\r\n const subtotalRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'd37878a0-d2b3-4e86-b7ec-dfc558ab67ed',\r\n 2,\r\n 'sm',\r\n ) as BTGridRowPrimary;\r\n\r\n subtotalRow.isHoverable = true;\r\n\r\n subtotalRow.cells[0].cellTriggersBTPopover = true;\r\n subtotalRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(subtotalForAllTotals),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n subtotalRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n subtotalRow.cells[0].cellContent =
    {formatNumberAsCurrency(subtotalForAllTotals)}
    ;\r\n subtotalRow.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [contentRows, ...dataRows, subtotalRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [project_EditBiddersRanges, setDisplayedPopoverInfo, t],\r\n );\r\n\r\n return { generateBidSummary_BidPackage_Totals_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_BidPackage_Totals;\r\n","import Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { Alternate } from '../../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { Fee } from '../../../../../../classes/odata/fee';\r\nimport { Project } from '../../../../../../classes/odata/project';\r\nimport { generateEmptyGridRowWithEmptyCells_Base } from '../../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n} from '../../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport { FeeTypes } from '../../../../../enums/fee-enum';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_Fees_Alternate_SubGrid: (\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n bidPackages: BidPackage[],\r\n alternate: Alternate,\r\n padForClassificationsSpacing: boolean,\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_Fees_Alternate = (): ReturnValue => {\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n // TODO - this needs to be able to be used dynamically, which should work fine as long as the dependencies are provided to the method\r\n // and not the custom hook itself\r\n const generateBidSummary_Fees_Alternate_SubGrid = useCallback(\r\n (\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n bidPackages: BidPackage[],\r\n alternate: Alternate,\r\n padForClassificationsSpacing: boolean,\r\n ): BTSubGrid => {\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '9d2b42af-4759-4f40-93c6-a5e2e2897e55',\r\n 1,\r\n padForClassificationsSpacing ? 'xl' : 'md',\r\n );\r\n headerRow.showBottomBorder = true;\r\n\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n let total = new Big(\r\n Project.calculateAlternateAmountForAllBidPackages(bidPackages, alternate),\r\n );\r\n\r\n fees.forEach((currFee) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currFee.id!, 0, 'md');\r\n newDataRow.isHoverable = true;\r\n newDataRow.showBottomBorder = true;\r\n\r\n const currFeeValue =\r\n currFee.calculatedValues.find((v) => v.alternateId === alternate.id)?.calculatedValue ||\r\n 0;\r\n\r\n let currFeeIsOrReferencesLumpSum = currFee.feeType === FeeTypes.LumpSum;\r\n\r\n // If the current fee is a percentage of another fee, find the last referenced fee (if there is a chain of references)\r\n // and check if it's a \"lump sum\" fee.\r\n // We want to show \"-\" for \"lump sum\" fees or fees that reference \"lump sum\" fees in this particular grid column.\r\n if (currFee.feeType === FeeTypes.Percent) {\r\n const referencedFee = Fee.getLastReferencedFeeForPercentFee(currFee, fees);\r\n\r\n if (referencedFee.feeType === FeeTypes.LumpSum) {\r\n currFeeIsOrReferencesLumpSum = true;\r\n }\r\n }\r\n\r\n newDataRow.cells.push({\r\n cellTriggersBTPopover: !(projectHasFeeCalculationFailure || currFeeIsOrReferencesLumpSum),\r\n onCellMouseEnter: (e) => {\r\n if (!(projectHasFeeCalculationFailure || currFeeIsOrReferencesLumpSum)) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(currFeeValue),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n },\r\n onCellMouseLeave: () => {\r\n setDisplayedPopoverInfo(null);\r\n },\r\n cellWidth: 'md',\r\n cellContent: (\r\n
    \r\n {projectHasFeeCalculationFailure || currFeeIsOrReferencesLumpSum\r\n ? '―'\r\n : formatNumberAsCurrency(currFeeValue)}\r\n
    \r\n ),\r\n cellHorizontalAlignment: 'right',\r\n });\r\n\r\n // We do not add \"subtotal\", \"lump sum\" fees, or referenced \"lump sum\" fees, to the total, and only\r\n // include enabled alternates\r\n if (\r\n alternate.enabled &&\r\n currFee.feeType !== FeeTypes.Subtotal &&\r\n !currFeeIsOrReferencesLumpSum\r\n ) {\r\n total = total.add(new Big(currFeeValue));\r\n }\r\n\r\n if (padForClassificationsSpacing) {\r\n newDataRow.cells.push({\r\n cellWidth: 'md',\r\n cellContent:
    ,\r\n });\r\n }\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Totals row\r\n const totalsRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '4122c06e-9858-4d2c-9fbc-77bd51a0b1ea',\r\n 0,\r\n 'md',\r\n );\r\n\r\n const newDataCell: BTGridCell = {\r\n cellTriggersBTPopover: !projectHasFeeCalculationFailure,\r\n onCellMouseEnter: (e) => {\r\n if (!projectHasFeeCalculationFailure) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(total),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n },\r\n onCellMouseLeave: () => {\r\n setDisplayedPopoverInfo(null);\r\n },\r\n cellContent: (\r\n
    {projectHasFeeCalculationFailure ? '―' : formatNumberAsCurrency(total)}
    \r\n ),\r\n cellWidth: 'md',\r\n cellHorizontalAlignment: 'right',\r\n };\r\n\r\n totalsRow.cells.push(newDataCell);\r\n\r\n if (padForClassificationsSpacing) {\r\n totalsRow.cells.push({\r\n cellWidth: 'md',\r\n cellContent:
    ,\r\n });\r\n }\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [...dataRows, totalsRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [setDisplayedPopoverInfo],\r\n );\r\n\r\n return { generateBidSummary_Fees_Alternate_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_Fees_Alternate;\r\n","import React, { useCallback } from 'react';\r\nimport { Fee } from '../../../../../../classes/odata/fee';\r\nimport { generateEmptyGridRowWithEmptyCells_Base } from '../../../../../../utils/btgrid';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_Fees_Alternate_Placeholder_SubGrid: (testId: string, fees: Fee[]) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_Fees_Alternate_Placeholder = (): ReturnValue => {\r\n // TODO - this needs to be able to be used dynamically, which should work fine as long as the dependencies are provided to the method\r\n // and not the custom hook i tself\r\n const generateBidSummary_Fees_Alternate_Placeholder_SubGrid = useCallback(\r\n (testId: string, fees: Fee[]): BTSubGrid => {\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '2b3a5598-9851-48e1-ab28-bd6e6014c614',\r\n 1,\r\n 'fill',\r\n );\r\n headerRow.showBottomBorder = true;\r\n\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n fees.forEach((currFee) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currFee.id!, 0, 'sm');\r\n newDataRow.isHoverable = true;\r\n newDataRow.showBottomBorder = true;\r\n\r\n for (let i = 0; i < 6; i++) {\r\n newDataRow.cells.unshift({\r\n cellContent:
    ,\r\n cellWidth: 'sm',\r\n });\r\n }\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Totals row\r\n const totalsRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'af2025de-434f-4be8-853f-f137d1531b67',\r\n 0,\r\n 'sm',\r\n );\r\n\r\n for (let i = 0; i < 6; i++) {\r\n totalsRow.cells.unshift({\r\n cellContent:
    ,\r\n cellWidth: 'sm',\r\n });\r\n }\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [...dataRows, totalsRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [],\r\n );\r\n\r\n return { generateBidSummary_Fees_Alternate_Placeholder_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_Fees_Alternate_Placeholder;\r\n","import Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { Fee } from '../../../../../../classes/odata/fee';\r\nimport { Project } from '../../../../../../classes/odata/project';\r\nimport { generateEmptyGridRowWithEmptyCells_Base } from '../../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n} from '../../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport { FeeTypes } from '../../../../../enums/fee-enum';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_Fees_BidAmount_SubGrid: (\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n bidPackages: BidPackage[],\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_Fees_BidAmount = (): ReturnValue => {\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n const generateBidSummary_Fees_BidAmount_SubGrid = useCallback(\r\n (\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n bidPackages: BidPackage[],\r\n ): BTSubGrid => {\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'a8495cb3-c2b4-4292-911d-22edacd24873',\r\n 1,\r\n 'fill',\r\n );\r\n headerRow.showBottomBorder = true;\r\n\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n let total = new Big(Project.calculateBaseEstimateAmount(bidPackages));\r\n\r\n fees.forEach((currFee) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currFee.id!, 1, 'sm');\r\n newDataRow.isHoverable = true;\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n const currFeeValue =\r\n currFee.calculatedValues.find((v) => v.feeId === currFee.id && !v.alternateId)\r\n ?.calculatedValue || 0;\r\n\r\n if (!projectHasFeeCalculationFailure) {\r\n newDataRow.cells[0].cellTriggersBTPopover = true;\r\n newDataRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(currFeeValue),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n }\r\n\r\n newDataRow.cells[0].cellContent = (\r\n
    {projectHasFeeCalculationFailure ? '―' : formatNumberAsCurrency(currFeeValue)}
    \r\n );\r\n\r\n // We do not add \"subtotal\" fees, to the total\r\n if (currFee.feeType !== FeeTypes.Subtotal) {\r\n total = total.add(new Big(currFeeValue));\r\n }\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Totals row\r\n const totalsRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '1287cc6c-7adc-4437-b0e4-415c744cb5f5',\r\n 1,\r\n 'sm',\r\n );\r\n\r\n if (!projectHasFeeCalculationFailure) {\r\n totalsRow.cells[0].cellTriggersBTPopover = true;\r\n totalsRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(total),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n }\r\n totalsRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n totalsRow.cells[0].cellContent = (\r\n
    {projectHasFeeCalculationFailure ? '―' : formatNumberAsCurrency(total)}
    \r\n );\r\n totalsRow.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [...dataRows, totalsRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [setDisplayedPopoverInfo],\r\n );\r\n\r\n return { generateBidSummary_Fees_BidAmount_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_Fees_BidAmount;\r\n","import { useCallback } from 'react';\r\nimport { Fee } from '../../../../../../classes/odata/fee';\r\nimport { generateEmptyGridRowWithEmptyCells_Base } from '../../../../../../utils/btgrid';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_Fees_Classifications_SubGrid: (testId: string, fees: Fee[]) => BTSubGrid;\r\n}\r\n\r\n// This subgrid is just a placeholder to space things out in the fees grid to match the classifications part of the bid package grid\r\nconst useBidSummary_Fees_Classifications = (): ReturnValue => {\r\n const generateBidSummary_Fees_Classifications_SubGrid = useCallback(\r\n (testId: string, fees: Fee[]): BTSubGrid => {\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'b38fe649-beec-4414-91ba-e07f1104f91c',\r\n 1,\r\n 'fill',\r\n );\r\n headerRow.showBottomBorder = true;\r\n\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n fees.forEach((currFee) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currFee.id!, 7, 'sm');\r\n newDataRow.isHoverable = true;\r\n newDataRow.showBottomBorder = true;\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Totals row\r\n const totalsRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '73d12134-5bf0-45a8-b94a-77cf53d1fe55',\r\n 7,\r\n 'sm',\r\n );\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [...dataRows, totalsRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [],\r\n );\r\n\r\n return { generateBidSummary_Fees_Classifications_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_Fees_Classifications;\r\n","import Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { Fee } from '../../../../../../classes/odata/fee';\r\nimport { Project } from '../../../../../../classes/odata/project';\r\nimport { generateEmptyGridRowWithEmptyCells_Base } from '../../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n} from '../../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport { FeeTypes } from '../../../../../enums/fee-enum';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_Fees_Contingencies_SubGrid: (\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n bidPackages: BidPackage[],\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_Fees_Contingencies = (): ReturnValue => {\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n const generateBidSummary_Fees_Contingencies_SubGrid = useCallback(\r\n (\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n bidPackages: BidPackage[],\r\n ): BTSubGrid => {\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '961c23a7-2fdc-416c-a56a-2e7b5cef9576',\r\n 1,\r\n 'fill',\r\n );\r\n headerRow.showBottomBorder = true;\r\n\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n let total = new Big(Project.calculateContingencyAmountForAllBidPackages(bidPackages));\r\n\r\n fees.forEach((currFee) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currFee.id!, 2, 'sm');\r\n newDataRow.isHoverable = true;\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.cells[1].cellHorizontalAlignment = 'right';\r\n\r\n const currFeeValue =\r\n currFee.calculatedValues.find((v) => v.feeId === currFee.id && !v.alternateId)\r\n ?.calculatedContingencyValue || 0;\r\n\r\n let currFeeIsOrReferencesLumpSum = currFee.feeType === FeeTypes.LumpSum;\r\n\r\n // If the current fee is a percentage of another fee, find the last referenced fee (if there is a chain of references)\r\n // and check if it's a \"lump sum\" fee.\r\n // We want to show \"-\" for \"lump sum\" fees or fees that reference \"lump sum\" fees in this particular grid column.\r\n if (currFee.feeType === FeeTypes.Percent) {\r\n const referencedFee = Fee.getLastReferencedFeeForPercentFee(currFee, fees);\r\n\r\n if (referencedFee.feeType === FeeTypes.LumpSum) {\r\n currFeeIsOrReferencesLumpSum = true;\r\n }\r\n }\r\n\r\n newDataRow.cells[1].cellTriggersBTPopover = !(\r\n projectHasFeeCalculationFailure || currFeeIsOrReferencesLumpSum\r\n );\r\n newDataRow.cells[1].onCellMouseEnter = (e) => {\r\n if (!(projectHasFeeCalculationFailure || currFeeIsOrReferencesLumpSum)) {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(currFeeValue),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n }\r\n };\r\n newDataRow.cells[1].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n newDataRow.cells[1].cellContent = (\r\n
    \r\n {projectHasFeeCalculationFailure || currFeeIsOrReferencesLumpSum\r\n ? '―'\r\n : formatNumberAsCurrency(currFeeValue)}\r\n
    \r\n );\r\n\r\n if (currFee.feeType !== FeeTypes.Subtotal && !currFeeIsOrReferencesLumpSum) {\r\n total = total.add(new Big(currFeeValue));\r\n }\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Totals row\r\n const totalsRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'c62c4493-2567-4e86-aaa6-dae1f31eede3',\r\n 2,\r\n 'sm',\r\n );\r\n\r\n if (!projectHasFeeCalculationFailure) {\r\n totalsRow.cells[totalsRow.cells.length - 1].cellTriggersBTPopover = true;\r\n totalsRow.cells[totalsRow.cells.length - 1].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(total),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n totalsRow.cells[totalsRow.cells.length - 1].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n }\r\n totalsRow.cells[totalsRow.cells.length - 1].cellContent = (\r\n
    {projectHasFeeCalculationFailure ? '―' : formatNumberAsCurrency(total)}
    \r\n );\r\n totalsRow.cells[totalsRow.cells.length - 1].cellHorizontalAlignment = 'right';\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [...dataRows, totalsRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [setDisplayedPopoverInfo],\r\n );\r\n\r\n return { generateBidSummary_Fees_Contingencies_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_Fees_Contingencies;\r\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport './FeeCalculationFailureNotification.scss';\n\ninterface Props {\n isReadOnly: boolean;\n onRetryClick: () => void;\n}\n\nconst FeeCalculationFailureNotification: React.FC = (props) => {\n const { t } = useTranslation();\n const [retryButtonClicked, setRetryButtonClicked] = useState(false);\n\n return (\n
    \n
    \n {!retryButtonClicked\n ? t('bid-summary:feeCalculationFailure')\n : t('bid-summary:feeCalculationRequested')}\n
    \n {!props.isReadOnly && !retryButtonClicked ? (\n <>\n  \n {\n props.onRetryClick();\n setRetryButtonClicked(true);\n }}\n >\n {t('general:clickHereToRetry')}\n
    \n \n ) : (\n <>\n )}\n \n );\n};\n\nexport default FeeCalculationFailureNotification;\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Fee } from '../../../../../../classes/odata/fee';\r\nimport GeneralConstants from '../../../../../../constants/general';\r\nimport { generateEmptyGridRowWithEmptyCells_Primary } from '../../../../../../utils/btgrid';\r\nimport { convertFeeTypeToFeeTypeName } from '../../../../../../utils/feeLabel';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n formatNumberAsPercentage,\r\n} from '../../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport { FeeTypes } from '../../../../../enums/fee-enum';\r\nimport useHelperHook from '../../../helper-hooks/useHelperHook';\r\nimport useBidSummaryPageContext from '../../BidSummaryPageContext';\r\nimport FeeCalculationFailureNotification from '../../components/FeeCalculationFailureNotification';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_Fees_Fees_SubGrid: (\r\n isProjectAdmin: boolean,\r\n isProjectContributor: boolean,\r\n isProjectFrozen: boolean,\r\n isReadOnly: boolean,\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_Fees_Fees = (): ReturnValue => {\r\n const { getUpdatableInputElement } = useHelperHook();\r\n const { t } = useTranslation();\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n const {\r\n feeAmount_Change,\r\n feeAmount_Blur,\r\n feeCalculation_Request,\r\n fees_Edit,\r\n } = useBidSummaryPageContext();\r\n\r\n const collapsibleIconJSXElementFactory = (element: JSX.Element): JSX.Element => (\r\n

    {element}

    \r\n );\r\n\r\n const generateBidSummary_Fees_Fees_SubGrid = useCallback(\r\n (\r\n isProjectAdmin: boolean,\r\n isProjectContributor: boolean,\r\n isProjectFrozen: boolean,\r\n isReadOnly: boolean,\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n ): BTSubGrid => {\r\n const cellWidths: BTGridCellWidths[] = ['lg', 'sm', 'fill'];\r\n\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Primary(\r\n '8029f52b-e1ed-4640-aa63-31919563d739',\r\n 1,\r\n 'fill',\r\n );\r\n headerRow.showBottomBorder = true;\r\n headerRow.groupingInfo = {\r\n isGroupedRow: false,\r\n order: null,\r\n groupingLevel: null,\r\n groupingKey1: 'FeesCollapsibleHeader',\r\n groupingKey2: null,\r\n globalCollapseResponseKey: null,\r\n globalCollapseTriggerKey: null,\r\n };\r\n\r\n if (fees.length > 0) {\r\n headerRow.isCollapsibleTrigger = true;\r\n headerRow.collapsibleIconJSXElementFactory = collapsibleIconJSXElementFactory;\r\n }\r\n\r\n const isEditable = isProjectAdmin && !isReadOnly;\r\n headerRow.cells[0].cellContent = (\r\n
    \r\n

    \r\n {t('fees:fees')}\r\n \r\n {\r\n // We want to swallow the event here to prevent the click from triggering the collapsible grid row\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n // If the user is a project admin, we want to allow the edit fees modal to open\r\n if (isEditable) {\r\n fees_Edit();\r\n }\r\n }}\r\n title={isProjectAdmin ? t('fees:editFees') : t('fees:invalidPermissionToEditFees')}\r\n />\r\n \r\n

    \r\n {projectHasFeeCalculationFailure ? (\r\n {\r\n // We want to swallow the event here to prevent the click from triggering the collapsible grid row\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }}\r\n >\r\n \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n \r\n );\r\n\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n fees.forEach((currFee) => {\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Primary(\r\n currFee.id!,\r\n 1,\r\n cellWidths[0],\r\n );\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.isHoverable = true;\r\n newDataRow.groupingInfo = {\r\n isGroupedRow: false,\r\n order: null,\r\n groupingLevel: null,\r\n groupingKey1: 'FeesCollapsibleHeader',\r\n groupingKey2: null,\r\n globalCollapseResponseKey: null,\r\n globalCollapseTriggerKey: null,\r\n };\r\n newDataRow.cells[0].frozenOnHorizontalScroll = true;\r\n newDataRow.cells[0].trimTextOnOverflow = true;\r\n newDataRow.cells[0].cellContent = (\r\n // NOTE: The nested divs are important here, for the cell content overflow CSS to work correctly\r\n
    \r\n
    {currFee.name}
    \r\n
    \r\n );\r\n\r\n newDataRow.cells[0].cellTriggersBTPopover = true;\r\n newDataRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: currFee.name || '',\r\n title: '',\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n\r\n newDataRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n\r\n const feeTypeLabel = convertFeeTypeToFeeTypeName(\r\n t,\r\n currFee.feeType!,\r\n currFee.referenceFeeName,\r\n );\r\n\r\n const cell: BTGridCell = {\r\n cellContent: <>,\r\n cellWidth: cellWidths[1],\r\n cellTriggersBTPopover: true,\r\n onCellMouseEnter: (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title:\r\n currFee.feeType && currFee.feeType === FeeTypes.LumpSum\r\n ? formatNumberAsCurrencyFull(currFee.amount || 0)\r\n : `${formatNumberAsPercentage(\r\n currFee.amount || 0,\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MINIMUM_FRACTION_DIGITS,\r\n GeneralConstants.DECIMAL_PRECISION_FORMAT.MAXIMUM_FRACTION_DIGITS,\r\n )}`,\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n },\r\n onCellMouseLeave: () => {\r\n setDisplayedPopoverInfo(null);\r\n },\r\n };\r\n if (isReadOnly) {\r\n cell.cellContent = (\r\n
    \r\n
    \r\n {currFee.feeType && currFee.feeType === FeeTypes.LumpSum\r\n ? formatNumberAsCurrency(currFee.amount || 0)\r\n : formatNumberAsPercentage(currFee.amount || 0)}\r\n
    \r\n
    \r\n );\r\n } else {\r\n cell.cellContent = (\r\n
    \r\n
    \r\n {getUpdatableInputElement(\r\n currFee,\r\n 'amount',\r\n 'number',\r\n true,\r\n (updatedObject: unknown) => {\r\n const updatedFee = updatedObject as Fee;\r\n feeAmount_Change({ feeName: updatedFee.name!, amount: updatedFee.amount! });\r\n },\r\n (field: string, updatedObject: unknown) => {\r\n const updatedFee = updatedObject as Fee;\r\n feeAmount_Blur({ feeName: updatedFee.name!, amount: updatedFee.amount! });\r\n },\r\n undefined,\r\n currFee.feeType && currFee.feeType === FeeTypes.LumpSum ? 'decimal' : 'percent',\r\n )}\r\n
    \r\n
    \r\n );\r\n }\r\n\r\n newDataRow.cells.push(cell);\r\n\r\n newDataRow.cells.push({\r\n cellContent:
    {feeTypeLabel}
    ,\r\n cellWidth: cellWidths[2],\r\n });\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n // Totals row\r\n const totalsRow = generateEmptyGridRowWithEmptyCells_Primary(\r\n '6cadaf0f-48db-4922-b159-817626fa4711',\r\n 2,\r\n cellWidths[0],\r\n );\r\n totalsRow.cells[1].cellWidth = cellWidths[1];\r\n totalsRow.cells[0].cellContent =

    {t('general:grandTotal')}

    ;\r\n headerRow.showBottomBorder = true;\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [...dataRows, totalsRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [\r\n feeAmount_Blur,\r\n feeAmount_Change,\r\n feeCalculation_Request,\r\n fees_Edit,\r\n getUpdatableInputElement,\r\n setDisplayedPopoverInfo,\r\n t,\r\n ],\r\n );\r\n\r\n return { generateBidSummary_Fees_Fees_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_Fees_Fees;\r\n","import Big from 'big.js';\r\nimport React, { useCallback, useContext } from 'react';\r\nimport { Alternate } from '../../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../../classes/odata/bid-package';\r\nimport { Fee } from '../../../../../../classes/odata/fee';\r\nimport { Project } from '../../../../../../classes/odata/project';\r\nimport { generateEmptyGridRowWithEmptyCells_Base } from '../../../../../../utils/btgrid';\r\nimport {\r\n formatNumberAsCurrency,\r\n formatNumberAsCurrencyFull,\r\n} from '../../../../../../utils/general';\r\nimport { BTPopoverContext } from '../../../../../common-page-components/popover/BTPopoverContext';\r\nimport { FeeTypes } from '../../../../../enums/fee-enum';\r\n\r\ninterface ReturnValue {\r\n generateBidSummary_Fees_Totals_SubGrid: (\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n bidPackages: BidPackage[],\r\n alternates: Alternate[],\r\n padForNotesSectionSpacing: boolean,\r\n ) => BTSubGrid;\r\n}\r\n\r\nconst useBidSummary_Fees_Totals = (): ReturnValue => {\r\n const { setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n const generateBidSummary_Fees_Totals_SubGrid = useCallback(\r\n (\r\n projectHasFeeCalculationFailure: boolean,\r\n testId: string,\r\n fees: Fee[],\r\n bidPackages: BidPackage[],\r\n alternates: Alternate[],\r\n padForNotesSectionSpacing: boolean,\r\n ): BTSubGrid => {\r\n const headerRow = generateEmptyGridRowWithEmptyCells_Base(\r\n 'b15a4864-cf6e-4a0c-b674-fdcc67b1e9c4',\r\n 1,\r\n 'fill',\r\n );\r\n headerRow.showBottomBorder = true;\r\n\r\n const dataRows: (BTGridRowPrimary | BTGridRowBase)[] = [];\r\n\r\n let total = new Big(0);\r\n\r\n fees.forEach((currFee) => {\r\n // NOTE: We create 2 columns, so we have an extra one to span the \"# of bids\" column from the bid packages grid above\r\n const newDataRow = generateEmptyGridRowWithEmptyCells_Base(currFee.id!, 2, 'sm');\r\n newDataRow.isHoverable = true;\r\n newDataRow.showBottomBorder = true;\r\n newDataRow.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n let currFeeTotal = new Big(0);\r\n currFee.calculatedValues\r\n .filter((v) => v.feeId === currFee.id)\r\n .forEach((v) => {\r\n currFeeTotal = currFeeTotal\r\n .add(new Big(v.calculatedValue || 0))\r\n .add(new Big(v.calculatedContingencyValue || 0));\r\n });\r\n\r\n if (!projectHasFeeCalculationFailure) {\r\n newDataRow.cells[0].cellTriggersBTPopover = true;\r\n newDataRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(currFeeTotal),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n newDataRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n }\r\n newDataRow.cells[0].cellContent = (\r\n
    {projectHasFeeCalculationFailure ? '―' : formatNumberAsCurrency(currFeeTotal)}
    \r\n );\r\n\r\n if (padForNotesSectionSpacing) {\r\n newDataRow.cells.unshift({\r\n cellContent:
    ,\r\n cellWidth: 'lg',\r\n });\r\n }\r\n\r\n // NOTE: SubTotal fees should be excluded, but anything else should be included\r\n if (currFee.feeType !== FeeTypes.Subtotal) {\r\n total = total.add(currFeeTotal);\r\n }\r\n\r\n dataRows.push(newDataRow);\r\n });\r\n\r\n total = total.add(Project.calculateProjectBidTotal(bidPackages, alternates));\r\n\r\n // Totals row\r\n const totalsRow = generateEmptyGridRowWithEmptyCells_Base(\r\n '74d294ff-79c8-4c35-b73a-b436c6a9b064',\r\n 2,\r\n 'sm',\r\n );\r\n\r\n if (!projectHasFeeCalculationFailure) {\r\n totalsRow.cells[0].cellTriggersBTPopover = true;\r\n totalsRow.cells[0].onCellMouseEnter = (e) => {\r\n setDisplayedPopoverInfo({\r\n element: e.target as HTMLElement,\r\n text: '',\r\n title: formatNumberAsCurrencyFull(total),\r\n placement: 'top',\r\n showCloseButton: false,\r\n });\r\n };\r\n totalsRow.cells[0].onCellMouseLeave = () => {\r\n setDisplayedPopoverInfo(null);\r\n };\r\n }\r\n totalsRow.cells[0].cellContent = (\r\n
    {projectHasFeeCalculationFailure ? '―' : formatNumberAsCurrency(total)}
    \r\n );\r\n totalsRow.cells[0].cellHorizontalAlignment = 'right';\r\n\r\n if (padForNotesSectionSpacing) {\r\n totalsRow.cells.unshift({\r\n cellContent:
    ,\r\n cellWidth: 'lg',\r\n });\r\n }\r\n\r\n return {\r\n id: testId,\r\n testId: testId,\r\n auxiliaryRows: [headerRow],\r\n rows: [...dataRows, totalsRow],\r\n addLeftPadding: false,\r\n };\r\n },\r\n [setDisplayedPopoverInfo],\r\n );\r\n\r\n return { generateBidSummary_Fees_Totals_SubGrid };\r\n};\r\n\r\nexport default useBidSummary_Fees_Totals;\r\n","import { sortBy } from 'lodash';\r\nimport { useCallback, useEffect, useState } from 'react';\r\nimport { Alternate } from '../../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\r\nimport { Fee } from '../../../../../classes/odata/fee';\r\nimport { BidSummaryOptions } from '../BidSummaryPage';\r\nimport useBidSummary_BidPackage_Alternate from './bid-package/useBidSummary_BidPackage_Alternate';\r\nimport useBidSummary_BidPackage_BidAmount from './bid-package/useBidSummary_BidPackage_BidAmount';\r\nimport useBidSummary_BidPackage_BidPackages from './bid-package/useBidSummary_BidPackage_BidPackages';\r\nimport useBidSummary_BidPackage_Classification from './bid-package/useBidSummary_BidPackage_Classification';\r\nimport useBidSummary_BidPackage_ComparisonToBaseEstimate from './bid-package/useBidSummary_BidPackage_ComparisonToBaseEstimate';\r\nimport useBidSummary_BidPackage_Contingencies from './bid-package/useBidSummary_BidPackage_Contingencies';\r\nimport useBidSummary_BidPackage_Notes from './bid-package/useBidSummary_BidPackage_Notes';\r\nimport useBidSummary_BidPackage_SecondBidderAnalysis from './bid-package/useBidSummary_BidPackage_SecondBidderAnalysis';\r\nimport useBidSummary_BidPackage_Totals from './bid-package/useBidSummary_BidPackage_Totals';\r\nimport useBidSummary_Fees_Alternate from './fees/useBidSummary_Fees_Alternate';\r\nimport useBidSummary_Fees_Alternate_Placeholder from './fees/useBidSummary_Fees_Alternate_Placeholder';\r\nimport useBidSummary_Fees_BidAmount from './fees/useBidSummary_Fees_BidAmount';\r\nimport useBidSummary_Fees_Classifications from './fees/useBidSummary_Fees_Classifications';\r\nimport useBidSummary_Fees_Contingencies from './fees/useBidSummary_Fees_Contingencies';\r\nimport useBidSummary_Fees_Fees from './fees/useBidSummary_Fees_Fees';\r\nimport useBidSummary_Fees_Totals from './fees/useBidSummary_Fees_Totals';\r\n\r\ninterface ReturnValue {\r\n generateSummaryGridSections: () => BTGridSection[];\r\n}\r\n\r\ninterface Props {\r\n bidSummaryOptions: BidSummaryOptions;\r\n isReadOnly: boolean;\r\n isProjectAdmin: boolean;\r\n isProjectContributor: boolean;\r\n isProjectFrozen: boolean;\r\n projectHasFeeCalculationFailure: boolean;\r\n bidPackages: BidPackage[];\r\n projectFees: Fee[];\r\n alternates: Alternate[];\r\n projectPreferences: Preferences;\r\n frozenBidPackageIds: string[];\r\n frozenBidPackageAdjustmentNoteIds: string[];\r\n}\r\n\r\nconst bidPackageGridSection_TestId = 'BidSummaryPage_BidPackage_GridSection';\r\nconst feesGridSection_TestId = 'BidSummaryPage_Fees_GridSection';\r\n\r\nconst useBidSummaryGrid = ({\r\n bidSummaryOptions,\r\n isReadOnly,\r\n isProjectAdmin,\r\n isProjectContributor,\r\n isProjectFrozen,\r\n projectHasFeeCalculationFailure,\r\n bidPackages,\r\n projectFees,\r\n alternates,\r\n projectPreferences,\r\n frozenBidPackageIds,\r\n frozenBidPackageAdjustmentNoteIds,\r\n}: Props): ReturnValue => {\r\n const {\r\n generateBidSummary_BidPackage_BidPackages_SubGrid,\r\n } = useBidSummary_BidPackage_BidPackages();\r\n\r\n const {\r\n generateBidSummary_BidPackage_Classification_SubGrid,\r\n } = useBidSummary_BidPackage_Classification();\r\n\r\n const { generateBidSummary_BidPackage_BidAmount_SubGrid } = useBidSummary_BidPackage_BidAmount();\r\n\r\n const {\r\n generateBidSummary_BidPackage_SecondBidderAnalysis_SubGrid,\r\n } = useBidSummary_BidPackage_SecondBidderAnalysis();\r\n\r\n const {\r\n generateBidSummary_BidPackage_ComparisonToBaseEstimate_SubGrid,\r\n } = useBidSummary_BidPackage_ComparisonToBaseEstimate();\r\n\r\n const { generateBidSummary_BidPackage_Alternate_SubGrid } = useBidSummary_BidPackage_Alternate({\r\n bidSummaryOptions,\r\n });\r\n\r\n const {\r\n generateBidSummary_BidPackage_Contingencies_SubGrid,\r\n } = useBidSummary_BidPackage_Contingencies();\r\n\r\n const { generateBidSummary_BidPackage_Notes_SubGrid } = useBidSummary_BidPackage_Notes();\r\n\r\n const { generateBidSummary_BidPackage_Totals_SubGrid } = useBidSummary_BidPackage_Totals();\r\n\r\n const { generateBidSummary_Fees_Fees_SubGrid } = useBidSummary_Fees_Fees();\r\n\r\n const { generateBidSummary_Fees_Classifications_SubGrid } = useBidSummary_Fees_Classifications();\r\n\r\n const { generateBidSummary_Fees_BidAmount_SubGrid } = useBidSummary_Fees_BidAmount();\r\n\r\n const {\r\n generateBidSummary_Fees_Alternate_Placeholder_SubGrid,\r\n } = useBidSummary_Fees_Alternate_Placeholder();\r\n\r\n const { generateBidSummary_Fees_Alternate_SubGrid } = useBidSummary_Fees_Alternate();\r\n\r\n const { generateBidSummary_Fees_Contingencies_SubGrid } = useBidSummary_Fees_Contingencies();\r\n\r\n const { generateBidSummary_Fees_Totals_SubGrid } = useBidSummary_Fees_Totals();\r\n\r\n // TODO - rename the other state variables on the bid package page with this convention\r\n\r\n // State variables for the bid package grid section\r\n const [subGrid_BidPackage_BidPackages, setSubGrid_BidPackages] = useState();\r\n const [subGrid_BidPackage_BidAmount, setSubGrid_BidAmount] = useState();\r\n\r\n const [subGrids_BidPackage_Alternates, setSubGrids_BidPackage_Alternates] = useState<\r\n BTSubGrid[]\r\n >();\r\n\r\n const [subGrid_BidPackage_Contingencies, setSubGrid_BidPackage_Contingencies] = useState<\r\n BTSubGrid\r\n >();\r\n const [subGrid_BidPackage_Totals, setSubGrid_BidPackage_Totals] = useState();\r\n const [subGrid_BidPackage_Classification, setSubGrid_BidPackage_Classification] = useState<\r\n BTSubGrid\r\n >();\r\n const [\r\n subGrid_BidPackage_SecondBidderAnalysis,\r\n setSubGrid_BidPackage_SecondBidderAnalysis,\r\n ] = useState();\r\n const [\r\n subGrid_BidPackage_ComparisonToBaseEstimate,\r\n setSubGrid_BidPackage_ComparisonToBaseEstimate,\r\n ] = useState();\r\n const [subGrid_BidPackage_Notes, setSubGrid_BidPackage_Notes] = useState();\r\n\r\n // State variables for the fees grid section\r\n const [subGrid_Fees_Classifications, setSubGrid_Fees_Classifications] = useState();\r\n const [subGrid_Fees_Fees, setSubGrid_Fees_Fees] = useState();\r\n const [subGrid_Fees_BidAmount, setSubGrid_Fees_BidAmount] = useState();\r\n const [subGrids_Fees_Alternates, setSubGrids_Fees_Alternates] = useState([]);\r\n const [subGrid_Fees_Contingencies, setSubGrid_Fees_Contingencies] = useState();\r\n const [subGrid_Fees_Totals, setSubGrid_Fees_Totals] = useState();\r\n\r\n const generateSummaryGridSections = useCallback((): BTGridSection[] => {\r\n const returnValue: BTGridSection[] = [];\r\n\r\n // Bid Packages Grid\r\n if (subGrid_BidPackage_BidPackages) {\r\n let bidPackagesSecondarySubGrids: BTSubGrid[] = [];\r\n\r\n if (bidSummaryOptions.displayClassifications && subGrid_BidPackage_Classification) {\r\n bidPackagesSecondarySubGrids.push(subGrid_BidPackage_Classification);\r\n }\r\n\r\n if (subGrid_BidPackage_BidAmount) {\r\n bidPackagesSecondarySubGrids.push(subGrid_BidPackage_BidAmount);\r\n }\r\n\r\n if (\r\n bidSummaryOptions.displayAnalysis &&\r\n subGrid_BidPackage_SecondBidderAnalysis &&\r\n subGrid_BidPackage_ComparisonToBaseEstimate\r\n ) {\r\n bidPackagesSecondarySubGrids.push(subGrid_BidPackage_SecondBidderAnalysis);\r\n bidPackagesSecondarySubGrids.push(subGrid_BidPackage_ComparisonToBaseEstimate);\r\n }\r\n\r\n if (subGrids_BidPackage_Alternates?.length) {\r\n bidPackagesSecondarySubGrids = bidPackagesSecondarySubGrids.concat(\r\n subGrids_BidPackage_Alternates,\r\n );\r\n }\r\n\r\n if (subGrid_BidPackage_Contingencies) {\r\n bidPackagesSecondarySubGrids.push(subGrid_BidPackage_Contingencies);\r\n }\r\n\r\n if (bidSummaryOptions.displayNotes && subGrid_BidPackage_Notes) {\r\n bidPackagesSecondarySubGrids.push(subGrid_BidPackage_Notes);\r\n }\r\n\r\n if (subGrid_BidPackage_Totals) {\r\n bidPackagesSecondarySubGrids.push(subGrid_BidPackage_Totals);\r\n }\r\n\r\n returnValue.push({\r\n id: bidPackageGridSection_TestId,\r\n testId: bidPackageGridSection_TestId,\r\n primaryGrid: subGrid_BidPackage_BidPackages,\r\n secondaryGrids: bidPackagesSecondarySubGrids,\r\n });\r\n }\r\n\r\n // Fees Grid\r\n if (subGrid_Fees_Fees) {\r\n let feesSecondarySubGrids: BTSubGrid[] = [];\r\n\r\n if (subGrid_Fees_Classifications) {\r\n feesSecondarySubGrids.push(subGrid_Fees_Classifications);\r\n }\r\n\r\n if (subGrid_Fees_BidAmount) {\r\n feesSecondarySubGrids.push(subGrid_Fees_BidAmount);\r\n }\r\n\r\n if (subGrids_Fees_Alternates.length) {\r\n feesSecondarySubGrids = feesSecondarySubGrids.concat(subGrids_Fees_Alternates);\r\n }\r\n\r\n if (subGrid_Fees_Contingencies) {\r\n feesSecondarySubGrids.push(subGrid_Fees_Contingencies);\r\n }\r\n\r\n if (subGrid_Fees_Totals) {\r\n feesSecondarySubGrids.push(subGrid_Fees_Totals);\r\n }\r\n\r\n returnValue.push({\r\n id: feesGridSection_TestId,\r\n testId: feesGridSection_TestId,\r\n primaryGrid: subGrid_Fees_Fees,\r\n secondaryGrids: feesSecondarySubGrids,\r\n });\r\n }\r\n\r\n return returnValue;\r\n }, [\r\n bidSummaryOptions,\r\n subGrid_BidPackage_BidAmount,\r\n subGrid_BidPackage_BidPackages,\r\n subGrid_BidPackage_Classification,\r\n subGrid_BidPackage_ComparisonToBaseEstimate,\r\n subGrid_BidPackage_Contingencies,\r\n subGrid_BidPackage_Notes,\r\n subGrid_BidPackage_SecondBidderAnalysis,\r\n subGrid_BidPackage_Totals,\r\n subGrid_Fees_BidAmount,\r\n subGrid_Fees_Classifications,\r\n subGrid_Fees_Contingencies,\r\n subGrid_Fees_Fees,\r\n subGrid_Fees_Totals,\r\n subGrids_BidPackage_Alternates,\r\n subGrids_Fees_Alternates,\r\n ]);\r\n\r\n useEffect(() => {\r\n const testId = `${bidPackageGridSection_TestId}_BidPackages_SubGrid`;\r\n\r\n setSubGrid_BidPackages(\r\n generateBidSummary_BidPackage_BidPackages_SubGrid(testId, bidSummaryOptions, bidPackages),\r\n );\r\n }, [bidSummaryOptions, bidPackages, generateBidSummary_BidPackage_BidPackages_SubGrid]);\r\n\r\n useEffect(() => {\r\n const testId = `${bidPackageGridSection_TestId}_Classifications_SubGrid`;\r\n\r\n setSubGrid_BidPackage_Classification(\r\n generateBidSummary_BidPackage_Classification_SubGrid(testId, bidPackages),\r\n );\r\n }, [bidPackages, generateBidSummary_BidPackage_Classification_SubGrid]);\r\n\r\n useEffect(() => {\r\n const testId = `${bidPackageGridSection_TestId}_BidAmount_SubGrid`;\r\n\r\n setSubGrid_BidAmount(\r\n generateBidSummary_BidPackage_BidAmount_SubGrid(\r\n isReadOnly,\r\n testId,\r\n bidPackages,\r\n frozenBidPackageIds,\r\n frozenBidPackageAdjustmentNoteIds,\r\n ),\r\n );\r\n }, [\r\n bidPackages,\r\n generateBidSummary_BidPackage_BidAmount_SubGrid,\r\n isReadOnly,\r\n frozenBidPackageIds,\r\n frozenBidPackageAdjustmentNoteIds,\r\n ]);\r\n\r\n useEffect(() => {\r\n const testId = `${bidPackageGridSection_TestId}_SecondBidderAnalysis_SubGrid`;\r\n\r\n setSubGrid_BidPackage_SecondBidderAnalysis(\r\n generateBidSummary_BidPackage_SecondBidderAnalysis_SubGrid(testId, bidPackages),\r\n );\r\n }, [bidPackages, generateBidSummary_BidPackage_SecondBidderAnalysis_SubGrid]);\r\n\r\n useEffect(() => {\r\n const testId = `${bidPackageGridSection_TestId}_ComparisonToBaseEstimate_SubGrid`;\r\n\r\n setSubGrid_BidPackage_ComparisonToBaseEstimate(\r\n generateBidSummary_BidPackage_ComparisonToBaseEstimate_SubGrid(testId, bidPackages),\r\n );\r\n }, [bidPackages, generateBidSummary_BidPackage_ComparisonToBaseEstimate_SubGrid]);\r\n\r\n useEffect(() => {\r\n const alternateSubGrids: BTSubGrid[] = [];\r\n\r\n sortBy(alternates, (a) => a.name).forEach((currAlternate) => {\r\n const testId = `${bidPackageGridSection_TestId}_Alternate_SubGrid_${currAlternate.name?.replace(\r\n / /g,\r\n '_',\r\n )}`;\r\n\r\n alternateSubGrids.push(\r\n generateBidSummary_BidPackage_Alternate_SubGrid(\r\n isReadOnly,\r\n testId,\r\n currAlternate,\r\n bidPackages,\r\n frozenBidPackageIds,\r\n frozenBidPackageAdjustmentNoteIds,\r\n ),\r\n );\r\n });\r\n\r\n setSubGrids_BidPackage_Alternates(alternateSubGrids);\r\n }, [\r\n alternates,\r\n bidPackages,\r\n frozenBidPackageIds,\r\n frozenBidPackageAdjustmentNoteIds,\r\n generateBidSummary_BidPackage_Alternate_SubGrid,\r\n isReadOnly,\r\n ]);\r\n\r\n useEffect(() => {\r\n const testId = `${bidPackageGridSection_TestId}_Contingencies_SubGrid`;\r\n\r\n setSubGrid_BidPackage_Contingencies(\r\n generateBidSummary_BidPackage_Contingencies_SubGrid(\r\n isReadOnly,\r\n testId,\r\n bidPackages,\r\n frozenBidPackageIds,\r\n ),\r\n );\r\n }, [\r\n bidPackages,\r\n frozenBidPackageIds,\r\n generateBidSummary_BidPackage_Contingencies_SubGrid,\r\n isReadOnly,\r\n ]);\r\n\r\n useEffect(() => {\r\n const testId = `${bidPackageGridSection_TestId}_Notes_SubGrid`;\r\n\r\n setSubGrid_BidPackage_Notes(\r\n generateBidSummary_BidPackage_Notes_SubGrid(isReadOnly, testId, bidPackages),\r\n );\r\n }, [bidPackages, generateBidSummary_BidPackage_Notes_SubGrid, isReadOnly]);\r\n\r\n useEffect(() => {\r\n const testId = `${bidPackageGridSection_TestId}_Totals_SubGrid`;\r\n\r\n setSubGrid_BidPackage_Totals(\r\n generateBidSummary_BidPackage_Totals_SubGrid(\r\n isReadOnly,\r\n testId,\r\n bidPackages,\r\n alternates,\r\n projectPreferences,\r\n ),\r\n );\r\n }, [\r\n isReadOnly,\r\n alternates,\r\n bidPackages,\r\n projectPreferences,\r\n generateBidSummary_BidPackage_Totals_SubGrid,\r\n ]);\r\n\r\n useEffect(() => {\r\n const testId = `${feesGridSection_TestId}_Fees_SubGrid`;\r\n\r\n setSubGrid_Fees_Fees(\r\n generateBidSummary_Fees_Fees_SubGrid(\r\n isProjectAdmin,\r\n isProjectContributor,\r\n isProjectFrozen,\r\n isReadOnly,\r\n projectHasFeeCalculationFailure,\r\n testId,\r\n projectFees,\r\n ),\r\n );\r\n }, [\r\n projectFees,\r\n generateBidSummary_Fees_Fees_SubGrid,\r\n isReadOnly,\r\n isProjectAdmin,\r\n projectHasFeeCalculationFailure,\r\n isProjectContributor,\r\n isProjectFrozen,\r\n ]);\r\n\r\n useEffect(() => {\r\n if (!bidSummaryOptions.displayClassifications) {\r\n setSubGrid_Fees_Classifications(undefined);\r\n return;\r\n }\r\n\r\n const testId = `${feesGridSection_TestId}_Classifications_SubGrid`;\r\n\r\n setSubGrid_Fees_Classifications(\r\n generateBidSummary_Fees_Classifications_SubGrid(testId, projectFees),\r\n );\r\n }, [\r\n projectFees,\r\n generateBidSummary_Fees_BidAmount_SubGrid,\r\n bidSummaryOptions,\r\n generateBidSummary_Fees_Classifications_SubGrid,\r\n ]);\r\n\r\n useEffect(() => {\r\n const testId = `${feesGridSection_TestId}_BidAmount_SubGrid`;\r\n\r\n setSubGrid_Fees_BidAmount(\r\n generateBidSummary_Fees_BidAmount_SubGrid(\r\n projectHasFeeCalculationFailure,\r\n testId,\r\n projectFees,\r\n bidPackages,\r\n ),\r\n );\r\n }, [\r\n projectFees,\r\n generateBidSummary_Fees_BidAmount_SubGrid,\r\n bidSummaryOptions,\r\n bidPackages,\r\n projectHasFeeCalculationFailure,\r\n ]);\r\n\r\n useEffect(() => {\r\n const placeholderTestId = `${feesGridSection_TestId}_Alternate_Placeholder_SubGrid`;\r\n\r\n const subGrids: BTSubGrid[] = [];\r\n\r\n if (bidSummaryOptions.displayAnalysis) {\r\n subGrids.push(\r\n generateBidSummary_Fees_Alternate_Placeholder_SubGrid(placeholderTestId, projectFees),\r\n );\r\n }\r\n\r\n sortBy(alternates, (a) => a.name).forEach((currAlternate) => {\r\n const testId = `${feesGridSection_TestId}_Alternate_SubGrid_${currAlternate.name?.replace(\r\n / /g,\r\n '_',\r\n )}`;\r\n\r\n subGrids.push(\r\n generateBidSummary_Fees_Alternate_SubGrid(\r\n projectHasFeeCalculationFailure,\r\n testId,\r\n projectFees,\r\n bidPackages,\r\n currAlternate,\r\n bidSummaryOptions.displayClassifications,\r\n ),\r\n );\r\n });\r\n\r\n setSubGrids_Fees_Alternates(subGrids);\r\n }, [\r\n projectFees,\r\n alternates,\r\n generateBidSummary_Fees_Alternate_SubGrid,\r\n bidSummaryOptions,\r\n generateBidSummary_Fees_Alternate_Placeholder_SubGrid,\r\n bidPackages,\r\n projectHasFeeCalculationFailure,\r\n ]);\r\n\r\n useEffect(() => {\r\n const testId = `${feesGridSection_TestId}_Contingencies_SubGrid`;\r\n\r\n setSubGrid_Fees_Contingencies(\r\n generateBidSummary_Fees_Contingencies_SubGrid(\r\n projectHasFeeCalculationFailure,\r\n testId,\r\n projectFees,\r\n bidPackages,\r\n ),\r\n );\r\n }, [\r\n projectFees,\r\n generateBidSummary_Fees_Contingencies_SubGrid,\r\n bidPackages,\r\n projectHasFeeCalculationFailure,\r\n ]);\r\n\r\n useEffect(() => {\r\n const testId = `${feesGridSection_TestId}_Totals_SubGrid`;\r\n\r\n setSubGrid_Fees_Totals(\r\n generateBidSummary_Fees_Totals_SubGrid(\r\n projectHasFeeCalculationFailure,\r\n testId,\r\n projectFees,\r\n bidPackages,\r\n alternates,\r\n bidSummaryOptions.displayNotes,\r\n ),\r\n );\r\n }, [\r\n projectFees,\r\n generateBidSummary_Fees_Totals_SubGrid,\r\n bidSummaryOptions,\r\n bidPackages,\r\n alternates,\r\n projectHasFeeCalculationFailure,\r\n ]);\r\n\r\n return { generateSummaryGridSections };\r\n};\r\n\r\nexport default useBidSummaryGrid;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport moment from 'moment';\r\nimport React, { useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory } from 'react-router';\r\nimport ApplicationRoutes from '../../../../../constants/routes';\r\nimport { isEnvironment } from '../../../../../utils/general';\r\nimport BTIconButtonToggle from '../../../../common-page-components/controls/icon-button-toggle/BTIconButtonToggle';\r\nimport NotificationServiceStatusMessage from '../../../../common-page-components/notification-service-status-message/NotificationServiceStatusMessage';\r\nimport SvgImage from '../../../../common-page-components/svg-image/SvgImage';\r\nimport { BidSummaryOptions } from '../BidSummaryPage';\r\nimport useBidSummaryPageContext from '../BidSummaryPageContext';\r\n\r\ninterface ReturnValue {\r\n generateBidSummaryPageHeader: (data: {\r\n liveUpdateRegistrationFailed: boolean;\r\n isReadOnly: boolean;\r\n projectInfo: DetailProjectInfo;\r\n projectImageBlobUrl: string | null;\r\n bidSummaryOptions: BidSummaryOptions;\r\n projectHasNotes: boolean;\r\n pageIsScrolled: boolean;\r\n anyEntitiesAreFrozen: boolean;\r\n projectSettingsAreFrozen: boolean;\r\n }) => JSX.Element;\r\n}\r\n\r\nconst useBidSummaryPageHeader = (): ReturnValue => {\r\n const { t } = useTranslation();\r\n\r\n const history = useHistory();\r\n\r\n const {\r\n bidSummary_DisplayOptionsChange,\r\n project_Close,\r\n project_EditNotes,\r\n project_ExportExcel,\r\n project_ShowInfo,\r\n keyboardShortcuts_Show,\r\n } = useBidSummaryPageContext();\r\n\r\n const generateBidSummaryPageHeader = useCallback(\r\n (data: {\r\n liveUpdateRegistrationFailed: boolean;\r\n isReadOnly: boolean;\r\n projectInfo: DetailProjectInfo;\r\n projectImageBlobUrl: string | null;\r\n bidSummaryOptions: BidSummaryOptions;\r\n projectHasNotes: boolean;\r\n pageIsScrolled: boolean;\r\n anyEntitiesAreFrozen: boolean;\r\n projectSettingsAreFrozen: boolean;\r\n }): JSX.Element => {\r\n return (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n {data.projectImageBlobUrl ? (\r\n
    \r\n \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n \r\n

    \r\n {data.projectInfo.name}\r\n

    \r\n\r\n {/* NOTE: Give the other stuff a little bit of a bottom margin so it visually matches the line height of the h1 element */}\r\n {/* NOTE: Give this a right margin so the WalkMe content has correct spacing */}\r\n
    \r\n project_ShowInfo(data.projectInfo)}\r\n />\r\n\r\n {\r\n keyboardShortcuts_Show();\r\n }}\r\n data-testid=\"BidSummaryPage_ViewKeyboardShortcutsIcon\"\r\n />\r\n
    \r\n
    \r\n\r\n
    \r\n \r\n
    \r\n
    \r\n\r\n
    \r\n {/* Show a snowflake icon when not in prod, to help QA debug when things got frozen during a test\r\n but they can't see the banner in the screenshot */}\r\n {!isEnvironment('prod') && data.anyEntitiesAreFrozen ? (\r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n \r\n {data.isReadOnly || data.projectSettingsAreFrozen ? (\r\n <>\r\n ) : (\r\n {\r\n history.push(`${ApplicationRoutes.PROJECT}/${data.projectInfo.id}`);\r\n }}\r\n value={false}\r\n />\r\n )}\r\n\r\n \r\n\r\n \r\n\r\n {data.isReadOnly ? (\r\n <>\r\n ) : (\r\n \r\n )}\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n
    \r\n {\r\n bidSummary_DisplayOptionsChange({\r\n ...data.bidSummaryOptions,\r\n displayAssignedToColumn: !data.bidSummaryOptions.displayAssignedToColumn,\r\n });\r\n }}\r\n value={data.bidSummaryOptions.displayAssignedToColumn}\r\n />\r\n\r\n {\r\n bidSummary_DisplayOptionsChange({\r\n ...data.bidSummaryOptions,\r\n displayClassifications: !data.bidSummaryOptions.displayClassifications,\r\n });\r\n }}\r\n value={data.bidSummaryOptions.displayClassifications}\r\n />\r\n\r\n {\r\n bidSummary_DisplayOptionsChange({\r\n ...data.bidSummaryOptions,\r\n displayAnalysis: !data.bidSummaryOptions.displayAnalysis,\r\n });\r\n }}\r\n value={data.bidSummaryOptions.displayAnalysis}\r\n />\r\n\r\n {\r\n bidSummary_DisplayOptionsChange({\r\n ...data.bidSummaryOptions,\r\n displayNotes: !data.bidSummaryOptions.displayNotes,\r\n });\r\n }}\r\n value={data.bidSummaryOptions.displayNotes}\r\n />\r\n
    \r\n
    \r\n
    \r\n \r\n \r\n );\r\n },\r\n [\r\n bidSummary_DisplayOptionsChange,\r\n history,\r\n keyboardShortcuts_Show,\r\n project_Close,\r\n project_EditNotes,\r\n project_ExportExcel,\r\n project_ShowInfo,\r\n t,\r\n ],\r\n );\r\n\r\n return { generateBidSummaryPageHeader };\r\n};\r\n\r\nexport default useBidSummaryPageHeader;\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class UpdateProjectAlternateEnabledStateCommand extends CommandBase {\r\n constructor(public projectId: string, public alternateName: string, public enabled: boolean) {\r\n super(\r\n 'DESTINI.BidDay.Commands.Projects.UpdateProjectAlternateEnabledState',\r\n `/project/update-project-alternate-enabled-state`,\r\n 'post',\r\n );\r\n }\r\n}\r\n","import { clone } from 'lodash';\r\nimport { UpdateProjectAlternateEnabledStateCommand } from '../../../../../classes/commands/project/update-project-alternate-enabled-state-command';\r\nimport { Alternate } from '../../../../../classes/odata/alternate';\r\n\r\ninterface ReturnValue {\r\n onChangeCallback_Alternate: (\r\n alternateCollection: Alternate[],\r\n alternateNameToUpdate: string,\r\n newValue: boolean,\r\n ) => Alternate[];\r\n\r\n createAlternateUpdateCommand: (\r\n projectId: string,\r\n alternateName: string,\r\n enabled: boolean,\r\n ) => ICommand | null;\r\n\r\n // Updates the alternate collection copy with the new data from the current alternate collection\r\n successFunction_Alternate: (\r\n command: ICommand,\r\n alternateCollectionToUpdate: Alternate[],\r\n alternateCollectionWithUpdatedData: Alternate[],\r\n ) => Alternate[];\r\n\r\n // Updates the current alternate collection with the data from the alternate collection copy\r\n errorFunction_Alternate: (\r\n command: ICommand,\r\n alternateCollectionToUpdate: Alternate[],\r\n alternateCollectionWithUpdatedData: Alternate[],\r\n ) => Alternate[];\r\n}\r\n\r\nconst useBidSummary_Alternates = (): ReturnValue => {\r\n return {\r\n onChangeCallback_Alternate,\r\n createAlternateUpdateCommand,\r\n successFunction_Alternate,\r\n errorFunction_Alternate,\r\n };\r\n};\r\n\r\nconst onChangeCallback_Alternate = (\r\n alternateCollection: Alternate[],\r\n alternateNameToUpdate: string,\r\n newValue: boolean,\r\n): Alternate[] => {\r\n const copiedCollection = [...alternateCollection];\r\n\r\n const existingIndex = copiedCollection.findIndex((v) => v.name === alternateNameToUpdate);\r\n if (existingIndex > -1) {\r\n const clonedAlternate = clone(copiedCollection[existingIndex]);\r\n\r\n clonedAlternate.enabled = newValue;\r\n copiedCollection[existingIndex] = clonedAlternate;\r\n }\r\n\r\n return copiedCollection;\r\n};\r\n\r\nconst createAlternateUpdateCommand = (\r\n projectId: string,\r\n alternateName: string,\r\n enabled: boolean,\r\n): ICommand | null => {\r\n return new UpdateProjectAlternateEnabledStateCommand(projectId, alternateName, enabled);\r\n};\r\n\r\nconst successFunction_Alternate = (\r\n command: ICommand,\r\n alternateCollectionToUpdate: Alternate[],\r\n alternateCollectionWithUpdatedData: Alternate[],\r\n): Alternate[] => {\r\n if (command instanceof UpdateProjectAlternateEnabledStateCommand) {\r\n const copiedCollection = [...alternateCollectionToUpdate];\r\n\r\n const existingIndex = copiedCollection.findIndex((v) => v.name === command.alternateName);\r\n if (existingIndex > -1) {\r\n const clonedAlternate = clone(copiedCollection[existingIndex]);\r\n const foundAlternate = alternateCollectionWithUpdatedData.find(\r\n (a) => a.name === command.alternateName,\r\n );\r\n if (foundAlternate) {\r\n clonedAlternate.enabled = foundAlternate.enabled;\r\n copiedCollection[existingIndex] = clonedAlternate;\r\n }\r\n }\r\n\r\n return copiedCollection;\r\n }\r\n\r\n return alternateCollectionToUpdate;\r\n};\r\n\r\nconst errorFunction_Alternate = (\r\n command: ICommand,\r\n alternateCollectionToUpdate: Alternate[],\r\n alternateCollectionWithUpdatedData: Alternate[],\r\n): Alternate[] => {\r\n if (command instanceof UpdateProjectAlternateEnabledStateCommand) {\r\n const copiedCollection = [...alternateCollectionToUpdate];\r\n\r\n const existingIndex = copiedCollection.findIndex((v) => v.name === command.alternateName);\r\n if (existingIndex > -1) {\r\n const clonedAlternate = clone(copiedCollection[existingIndex]);\r\n const foundAlternate = alternateCollectionWithUpdatedData.find(\r\n (a) => a.name === command.alternateName,\r\n );\r\n if (foundAlternate) {\r\n clonedAlternate.enabled = foundAlternate.enabled;\r\n copiedCollection[existingIndex] = clonedAlternate;\r\n }\r\n }\r\n\r\n return copiedCollection;\r\n }\r\n\r\n return alternateCollectionToUpdate;\r\n};\r\n\r\nexport default useBidSummary_Alternates;\r\n","import { cloneDeep } from 'lodash';\nimport { useCallback, useContext } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory } from 'react-router';\nimport { Alternate } from '../../../../../classes/odata/alternate';\nimport { BidPackage } from '../../../../../classes/odata/bid-package';\nimport { Bidder } from '../../../../../classes/odata/bidder';\nimport { Fee } from '../../../../../classes/odata/fee';\nimport { FeeCalculatedValues } from '../../../../../classes/odata/fee-calculated-values';\nimport ApplicationRoutes from '../../../../../constants/routes';\nimport { AuthenticationService } from '../../../../../services/authentication/authentication-service';\nimport { normalizeNullOrUndefined } from '../../../../../utils/general';\nimport { nameof } from '../../../../../utils/nameof';\nimport { areTrimmedStringsEqual } from '../../../../../utils/strings';\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\nimport { ChangeNotificationProjectInfo } from '../change-notification-project-info';\n\ninterface ProjectOrBidPackageChangeHandlerReturnValue {\n projectInfo: DetailProjectInfo;\n bidPackages: BidPackage[];\n alternates: Alternate[];\n fees: Fee[];\n}\n\ninterface ReturnValue {\n // The project change handler takes in various objects to update, and returns copies of those objects with the updated data\n projectChangeHandler: (\n message: DataChangedNotificationMessage,\n projectInfo: DetailProjectInfo,\n bidPackages: BidPackage[],\n alternates: Alternate[],\n fees: Fee[],\n users: User[], // Users that we need to set the \"assignedToUser\" property on a bid package\n ) => ProjectOrBidPackageChangeHandlerReturnValue;\n\n bidPackageChangeHandler: (\n message: DataChangedNotificationMessage,\n projectInfo: DetailProjectInfo,\n bidPackages: BidPackage[],\n alternates: Alternate[],\n fees: Fee[],\n updatedBidPackageTotals: BidPackage | null, // Updated bid package objects with updated totals properties\n users: User[], // Users that we need to set the \"assignedToUser\" property on a bid package\n ) => ProjectOrBidPackageChangeHandlerReturnValue;\n}\n\ninterface DataChangeHandler {\n onAdd: (entry: DataChangedEntry, sourceId: string) => Promise;\n onUpdate: (entry: DataChangedEntry, sourceId: string) => Promise;\n onDelete: (entry: DataChangedEntry, sourceId: string) => Promise;\n}\n\nconst useBidSummary_ChangeNotifications = (): ReturnValue => {\n const { t } = useTranslation();\n const history = useHistory();\n const { showErrorNotification, showInfoNotification } = useContext(NotificationPanelContext);\n\n function updateEntity(\n entityToUpdate: any | undefined, // eslint-disable-line @typescript-eslint/no-explicit-any\n entry: DataChangedEntry,\n ) {\n if (entityToUpdate === undefined) {\n return;\n }\n\n // Update entity with values provided in the data change entry\n Object.keys(entry.Values).forEach((key) => {\n entityToUpdate[key] = entry.Values[key];\n });\n }\n\n function updateEntityInArray(\n currentArrayValue: T[],\n entry: DataChangedEntry,\n entity: new (...args: any[]) => T, // eslint-disable-line @typescript-eslint/no-explicit-any\n sortValue: keyof T,\n ): void {\n // Get index of entity by ID\n const entityId = entry.Values['id'] as string;\n const index = currentArrayValue.findIndex((x) => x.id === entityId);\n // If the entity cannot be found, return\n if (index === -1) {\n return;\n }\n const updatedEntity = new entity({\n ...currentArrayValue[index], // Start with current values\n ...entry.Values, // Override with values provided in message\n });\n // Update in array\n currentArrayValue[index] = updatedEntity;\n\n currentArrayValue.sort((a, b) => {\n if (a[sortValue] < b[sortValue]) {\n return -1;\n } else if (a[sortValue] > b[sortValue]) {\n return 1;\n }\n\n return 0;\n });\n }\n\n function removeEntityFromArray(\n currentArrayValue: T[],\n entry: DataChangedEntry,\n ): void {\n // Get index of entity by ID\n const entityId = entry.Values['id'] as string;\n const index = currentArrayValue.findIndex((x) => x.id === entityId);\n // If the entity cannot be found, return\n if (index === -1) {\n return;\n }\n\n currentArrayValue.splice(index, 1);\n }\n\n function upsertEntityInArray(\n arrayToAddTo: T[],\n entry: DataChangedEntry,\n entity: new (...args: any[]) => T, // eslint-disable-line @typescript-eslint/no-explicit-any\n sortValue: keyof T,\n ): void {\n const newEntity = new entity({ ...entry.Values });\n const indexOfExistingEntity = arrayToAddTo.findIndex((v) => v.id === newEntity.id);\n\n if (indexOfExistingEntity === -1) {\n arrayToAddTo.push(newEntity);\n } else {\n arrayToAddTo[indexOfExistingEntity] = newEntity;\n }\n\n arrayToAddTo.sort((a, b) => {\n if (a[sortValue] < b[sortValue]) {\n return -1;\n } else if (a[sortValue] > b[sortValue]) {\n return 1;\n }\n\n return 0;\n });\n }\n\n // Gets an object with change handlers for CRUD operations for the specified entry type\n const getDataChangeHandlerMap = useCallback(\n (\n type: DataChangedEntryTypes_BidSummaryPage,\n projectInfo: DetailProjectInfo,\n bidPackages: BidPackage[],\n alternates: Alternate[],\n fees: Fee[],\n ): DataChangeHandler => {\n // NOTE: This operates directly on the bid packages parameter object\n const updateBidPackageChildEntity = async (\n bidPackageId: string,\n entry: DataChangedEntry,\n updater: (bidPackage: BidPackage, e: DataChangedEntry) => void,\n ): Promise => {\n const index = bidPackages.findIndex((x) => x.id === bidPackageId);\n // If the bid package cannot be found, return\n if (index === -1) {\n return;\n }\n const updatedBidPackage = new BidPackage({ ...bidPackages[index] });\n updater(updatedBidPackage, entry);\n bidPackages[index] = updatedBidPackage;\n };\n\n switch (type) {\n case 'Preference':\n return {\n onAdd: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do nothing here\n },\n onUpdate: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do nothing here\n },\n onDelete: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do nothing here\n },\n };\n\n case 'Project':\n return {\n onAdd: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We shouldn't get a change notification for an added project since\n // changes are scoped to a specific project\n },\n onUpdate: async (entry: DataChangedEntry, sourceId: string): Promise => {\n updateEntity(projectInfo, entry);\n },\n onDelete: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: This is handled explicitly in projectChangeHandler\n },\n };\n\n case 'BidPackage':\n return {\n onAdd: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We have to verify that the project ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const projectIdOfEntry = entry.Values[nameof('projectId')];\n if (projectInfo.id !== projectIdOfEntry) {\n return;\n }\n\n upsertEntityInArray(bidPackages, entry, BidPackage, 'code');\n },\n onUpdate: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We have to verify that the project ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const projectIdOfEntry = entry.Values[nameof('projectId')];\n if (projectInfo.id !== projectIdOfEntry) {\n return;\n }\n\n // Get index of entity by ID\n const entityId = entry.Values[nameof('id')] as string;\n const index = bidPackages.findIndex((x) => x.id === entityId);\n // If the entity cannot be found, return\n if (index === -1) {\n return;\n }\n const updatedEntity = new BidPackage({\n ...bidPackages[index], // Start with current values\n ...entry.Values,\n });\n\n const selectedBidderId = entry.Values['selectedBidderId'] as string;\n if (selectedBidderId) {\n const selectedBidder = bidPackages[index].bidders.find(\n (b) => b.id === selectedBidderId,\n );\n updatedEntity.selectedBidder = selectedBidder;\n } else {\n updatedEntity.selectedBidder = undefined;\n }\n\n // Update in array\n bidPackages[index] = updatedEntity;\n },\n onDelete: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n removeEntityFromArray(bidPackages, entry);\n },\n };\n\n case 'Bidder':\n return {\n onAdd: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We have to verify that the entity ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const bidPackageIdOfEntry = entry.Values[nameof('bidPackageId')] as string;\n if (!bidPackages.map((v) => v.id).includes(bidPackageIdOfEntry)) {\n return;\n }\n\n updateBidPackageChildEntity(sourceId, entry, (bp, e) => {\n const cloneOfBidders = [...bp.bidders];\n cloneOfBidders.push(new Bidder({ ...entry.Values }));\n bp.bidders = cloneOfBidders;\n });\n },\n onUpdate: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n updateBidPackageChildEntity(sourceId, entry, (bp, e) => {\n const bidderId = e.Values[nameof('id')] as string;\n const index = bp.bidders.findIndex((b) => b.id === bidderId);\n if (index === -1) {\n return;\n }\n const cloneOfBidders = [...bp.bidders];\n const updatedEntity = new Bidder({\n ...bp.bidders[index], // Start with current values\n ...entry.Values, // override with values from data changes\n });\n // Update in array\n cloneOfBidders[index] = updatedEntity;\n bp.bidders = cloneOfBidders;\n });\n },\n onDelete: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n updateBidPackageChildEntity(sourceId, entry, (bp, e) => {\n const bidderId = e.Values[nameof('id')] as string;\n const index = bp.bidders.findIndex((b) => b.id === bidderId);\n if (index !== -1) {\n const cloneOfBidders = [...bp.bidders];\n cloneOfBidders.splice(index, 1);\n bp.bidders = cloneOfBidders;\n }\n });\n },\n };\n\n case 'Adjustment':\n return {\n onAdd: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // no need to add anything.\n },\n onUpdate: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // no need to update anything.\n },\n onDelete: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // no need to delete anything.\n },\n };\n\n case 'Alternate':\n return {\n onAdd: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We have to verify that the project ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const projectIdOfEntry = entry.Values[nameof('projectId')];\n if (projectInfo.id !== projectIdOfEntry) {\n return;\n }\n\n upsertEntityInArray(alternates, entry, Alternate, 'name');\n },\n onUpdate: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n updateEntityInArray(alternates, entry, Alternate, 'name');\n },\n onDelete: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n removeEntityFromArray(alternates, entry);\n },\n };\n\n case 'Fee':\n return {\n onAdd: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We have to verify that the project ID is correct, as SignalR provides excess\n // data due to the way it groups subscriptions on the server\n const projectIdOfEntry = entry.Values[nameof('projectId')];\n if (projectInfo.id !== projectIdOfEntry) {\n return;\n }\n\n upsertEntityInArray(fees, entry, Fee, 'order');\n },\n onUpdate: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n updateEntityInArray(fees, entry, Fee, 'order');\n },\n onDelete: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n removeEntityFromArray(fees, entry);\n },\n };\n\n case 'FeeCalculatedValues':\n return {\n onAdd: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const addFeesFn = (feesToUpdate: Fee[]): void => {\n // Get index of fee by ID\n const feeId = entry.Values[nameof('feeId')] as string;\n const feeIndex = feesToUpdate.findIndex((x) => x.id === feeId);\n\n // If the fee cannot be found, return\n if (feeIndex === -1) {\n return;\n }\n\n // Clone calculated values\n const cloneOfFeeCalculatedValues = [...feesToUpdate[feeIndex].calculatedValues];\n\n // Add new values\n cloneOfFeeCalculatedValues.push(new FeeCalculatedValues({ ...entry.Values }));\n\n // Update fee and return\n feesToUpdate[feeIndex].calculatedValues = cloneOfFeeCalculatedValues;\n };\n\n addFeesFn(fees);\n },\n onUpdate: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const updateFeesFn = (feesToUpdate: Fee[]): void => {\n // Get index of the fee by ID\n const feeId = entry.Values[nameof('feeId')] as string;\n const feeIndex = feesToUpdate.findIndex((x) => x.id === feeId);\n\n // If the fee cannot be found, return\n if (feeIndex === -1) {\n return;\n }\n\n // Clone calculated values\n const cloneOfFeeCalculatedValues = [...feesToUpdate[feeIndex].calculatedValues];\n\n // Get index of the calculated values by ID\n const feeCalculatedValueId = entry.Values[\n nameof('id')\n ] as string;\n\n const feeCalculatedValueIndex = cloneOfFeeCalculatedValues.findIndex(\n (x) => x.id === feeCalculatedValueId,\n );\n\n // If the calculated values cannot be found, return\n if (feeCalculatedValueIndex === -1) {\n return;\n }\n\n // Update with the overridden values\n const updatedCalculatedValues = new FeeCalculatedValues({\n ...cloneOfFeeCalculatedValues[feeCalculatedValueIndex], // Start with current values\n ...entry.Values, // override with values from data changes\n });\n\n // Update calculated values\n cloneOfFeeCalculatedValues[feeCalculatedValueIndex] = updatedCalculatedValues;\n\n // Update fee and return\n feesToUpdate[feeIndex].calculatedValues = cloneOfFeeCalculatedValues;\n };\n\n updateFeesFn(fees);\n },\n onDelete: async (entry: DataChangedEntry, sourceId: string): Promise => {\n // NOTE: We do not have to check that the entry matches an entity ID, since we are matching\n // by ID, which is unique\n\n const deleteFeesFn = (feesToUpdate: Fee[]): void => {\n // Get index of the fee by ID\n const feeId = entry.Values[nameof('feeId')] as string;\n const feeIndex = feesToUpdate.findIndex((x) => x.id === feeId);\n\n // If the fee cannot be found, return\n if (feeIndex === -1) {\n return;\n }\n\n // Clone calculated values\n const cloneOfFeeCalculatedValues = [...feesToUpdate[feeIndex].calculatedValues];\n\n // Get index of the calculated values by ID\n const feeCalculatedValueId = entry.Values[\n nameof('id')\n ] as string;\n\n const feeCalculatedValueIndex = cloneOfFeeCalculatedValues.findIndex(\n (x) => x.id === feeCalculatedValueId,\n );\n\n // If the calculated values cannot be found, return\n if (feeCalculatedValueIndex === -1) {\n return;\n }\n\n // Remove from array\n cloneOfFeeCalculatedValues.splice(feeCalculatedValueIndex, 1);\n\n // Update fee and return\n feesToUpdate[feeIndex].calculatedValues = cloneOfFeeCalculatedValues;\n };\n\n deleteFeesFn(fees);\n },\n };\n }\n },\n [],\n );\n\n const projectChangeHandler = useCallback(\n (\n message: DataChangedNotificationMessage,\n projectInfo: DetailProjectInfo,\n bidPackages: BidPackage[],\n alternates: Alternate[],\n fees: Fee[],\n users: User[], // Users that we need to set the \"assignedToUser\" property on a bid package\n ): ProjectOrBidPackageChangeHandlerReturnValue => {\n // NOTE: We do deep clones here, since we are updating data once for all the updates in the message, so the performance should be fine\n const returnValue: ProjectOrBidPackageChangeHandlerReturnValue = {\n projectInfo: cloneDeep(projectInfo),\n bidPackages: cloneDeep(bidPackages),\n alternates: cloneDeep(alternates),\n fees: cloneDeep(fees),\n };\n\n // Check to see if someone deleted the Project\n const deletedProjectEntry = message.Deleted.find((entry) => entry.Type === 'Project');\n if (deletedProjectEntry) {\n // Display error message\n const projectName = deletedProjectEntry.Values[\n nameof('name')\n ] as string;\n showErrorNotification(\n t('general:error'),\n t('bid-summary:projectRemoved', { project: projectName, user: message.ChangedBy }),\n );\n\n // Return to home screen\n history.push(ApplicationRoutes.HOME);\n\n return returnValue;\n }\n\n // If this message closes the current project and isn't coming from the current user, we need to display a notification\n const closedProjectEntry = message.Updated.find(\n (entry) =>\n entry.Type === 'Project' &&\n entry.Values[nameof('isClosed')],\n );\n if (\n closedProjectEntry &&\n !areTrimmedStringsEqual(message.ChangedBy, AuthenticationService.currentUserInfo?.email)\n ) {\n // Display informational message\n showInfoNotification(t('project:projectClosed'), t('project:projectClosedMessage'));\n }\n\n message.Deleted.forEach((entry: DataChangedEntry) => {\n const handler = getDataChangeHandlerMap(\n entry.Type as DataChangedEntryTypes_BidSummaryPage,\n returnValue.projectInfo,\n returnValue.bidPackages,\n returnValue.alternates,\n returnValue.fees,\n );\n\n if (handler) {\n handler.onDelete(entry, message.SourceId);\n }\n });\n\n message.Added.forEach((entry: DataChangedEntry) => {\n const handler = getDataChangeHandlerMap(\n entry.Type as DataChangedEntryTypes_BidSummaryPage,\n returnValue.projectInfo,\n returnValue.bidPackages,\n returnValue.alternates,\n returnValue.fees,\n );\n\n if (handler) {\n entry = updateEntryValuesWithAssignedUserObject(entry, users);\n\n handler.onAdd(entry, message.SourceId);\n }\n });\n\n message.Updated.forEach((entry: DataChangedEntry) => {\n const handler = getDataChangeHandlerMap(\n entry.Type as DataChangedEntryTypes_BidSummaryPage,\n returnValue.projectInfo,\n returnValue.bidPackages,\n returnValue.alternates,\n returnValue.fees,\n );\n\n if (handler) {\n entry = updateEntryValuesWithAssignedUserObject(entry, users);\n\n handler.onUpdate(entry, message.SourceId);\n }\n });\n\n return returnValue;\n },\n [getDataChangeHandlerMap, history, showErrorNotification, showInfoNotification, t],\n );\n\n const bidPackageChangeHandler = useCallback(\n (\n message: DataChangedNotificationMessage,\n projectInfo: DetailProjectInfo,\n bidPackages: BidPackage[],\n alternates: Alternate[],\n fees: Fee[],\n updatedBidPackageTotals: BidPackage | null, // Updated bid package objects with updated totals properties\n users: User[], // Users that we need to set the \"assignedToUser\" property on a bid package\n ): ProjectOrBidPackageChangeHandlerReturnValue => {\n // NOTE: We do deep clones here, since we are updating data once for all the updates in the message, so the performance should be fine\n const returnValue: ProjectOrBidPackageChangeHandlerReturnValue = {\n projectInfo: cloneDeep(projectInfo),\n bidPackages: cloneDeep(bidPackages),\n alternates: cloneDeep(alternates),\n fees: cloneDeep(fees),\n };\n\n // Process deleted entities\n message.Deleted.forEach((entry: DataChangedEntry) => {\n const handler = getDataChangeHandlerMap(\n entry.Type as DataChangedEntryTypes_BidSummaryPage,\n returnValue.projectInfo,\n returnValue.bidPackages,\n returnValue.alternates,\n returnValue.fees,\n );\n\n if (handler) {\n handler.onDelete(entry, message.SourceId);\n }\n });\n\n // Process added entities\n message.Added.forEach((entry: DataChangedEntry) => {\n const handler = getDataChangeHandlerMap(\n entry.Type as DataChangedEntryTypes_BidSummaryPage,\n returnValue.projectInfo,\n returnValue.bidPackages,\n returnValue.alternates,\n returnValue.fees,\n );\n\n if (handler) {\n entry = updateEntryValuesWithAssignedUserObject(entry, users);\n\n handler.onAdd(entry, message.SourceId);\n }\n });\n\n // Process updated entities\n message.Updated.forEach(async (entry: DataChangedEntry) => {\n const handler = getDataChangeHandlerMap(\n entry.Type as DataChangedEntryTypes_BidSummaryPage,\n returnValue.projectInfo,\n returnValue.bidPackages,\n returnValue.alternates,\n returnValue.fees,\n );\n\n if (handler) {\n entry = updateEntryValuesWithAssignedUserObject(entry, users);\n\n handler.onUpdate(entry, message.SourceId);\n }\n });\n\n // Update totals\n if (updatedBidPackageTotals) {\n updateBidPackageTotals(returnValue.bidPackages, message.SourceId, updatedBidPackageTotals);\n }\n\n return returnValue;\n },\n [getDataChangeHandlerMap],\n );\n\n return { projectChangeHandler, bidPackageChangeHandler };\n};\n\nconst updateBidPackageTotals = (\n bidPackagesToUpdate: BidPackage[],\n bidPackageId: string,\n updatedBidPackageTotals: BidPackage, // Updated bid package objects with updated totals properties\n): void => {\n // Get index of entity by ID\n const index = bidPackagesToUpdate.findIndex((x) => x.id === bidPackageId);\n\n // If the entity cannot be found, return\n if (index === -1) {\n return;\n }\n\n const updatedEntity = new BidPackage({\n ...bidPackagesToUpdate[index], // Start with current values\n bidClassificationTotals: updatedBidPackageTotals?.bidClassificationTotals ?? [],\n lineItemsTotals: updatedBidPackageTotals?.lineItemsTotals ?? [],\n });\n\n updatedEntity.bidTotals = updatedBidPackageTotals.bidTotals.map((updatedBidTotal) => {\n // Get the matching bid total in the updated entity\n const matchingBidTotal = updatedEntity.bidTotals.find(\n (m) =>\n normalizeNullOrUndefined(updatedBidTotal.bidderId) ===\n normalizeNullOrUndefined(m.bidderId) &&\n normalizeNullOrUndefined(updatedBidTotal.alternateId) ===\n normalizeNullOrUndefined(m.alternateId),\n );\n\n // If the entity is dirty (ie. the user is currently editing it), don't replace it with a new bid total\n if (matchingBidTotal && matchingBidTotal.isDirty) {\n return matchingBidTotal;\n } else {\n return updatedBidTotal;\n }\n });\n\n // Update in array\n bidPackagesToUpdate[index] = updatedEntity;\n};\n\n// Checks if the data changed entry was for a bid package and the assigned user and returns a new\n// entry object with the assigned user object set. If this doesn't apply to the current entry, it\n// just returns the same entry.\nconst updateEntryValuesWithAssignedUserObject = (\n currEntry: DataChangedEntry,\n users: User[],\n): DataChangedEntry => {\n const bidPackageEntryTypeName: DataChangedEntryTypes_BidSummaryPage = 'BidPackage';\n\n // If assignedToUserId is present in entry.Values, add the assignedToUser prop\n // so it is set on the bid package\n if (\n currEntry.Type === bidPackageEntryTypeName &&\n currEntry.Values[nameof('assignedToUserId')] !== undefined\n ) {\n const assignedToUserId = currEntry.Values[nameof('assignedToUserId')] as\n | string\n | null;\n const assignedUser = !assignedToUserId ? null : users.find((v) => v.id === assignedToUserId);\n\n const copy = cloneDeep(currEntry);\n\n copy.Values[nameof('assignedToUser')] = assignedUser\n ? cloneDeep(assignedUser)\n : assignedUser;\n\n return copy;\n }\n\n return currEntry;\n};\n\nexport default useBidSummary_ChangeNotifications;\n","import { clone, cloneDeep, isEqual, sortBy, uniq } from 'lodash';\r\nimport React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory, useParams } from 'react-router';\r\nimport { Subscription } from 'rxjs';\r\nimport { AddEditProjectNotesToProjectCommand } from '../../../../classes/commands/project/add-edit-project-notes-to-project-command';\r\nimport { CloseProjectCommand } from '../../../../classes/commands/project/close-project-command';\r\nimport { ProjectFeesBatchCommand } from '../../../../classes/commands/project/fees/project-fees-batch-command';\r\nimport { UpdateProjectFeeCommand } from '../../../../classes/commands/project/fees/update-project-fee-command';\r\nimport { Adjustment } from '../../../../classes/odata/adjustment';\r\nimport { Alternate } from '../../../../classes/odata/alternate';\r\nimport { BidPackage } from '../../../../classes/odata/bid-package';\r\nimport { Fee } from '../../../../classes/odata/fee';\r\nimport { Project } from '../../../../classes/odata/project';\r\nimport GeneralConstants from '../../../../constants/general';\r\nimport EntityValidationConstants from '../../../../constants/general/entity-validation-constants';\r\nimport ApplicationRoutes from '../../../../constants/routes';\r\nimport { useObservableWithValue } from '../../../../hooks/observables/useObservable';\r\nimport {\r\n BidPackageApi,\r\n BidSummaryApi,\r\n FeeApi,\r\n FrozenEntitiesApi,\r\n PreferencesApi,\r\n ProjectApi,\r\n RecentProjectsApi,\r\n UserApi,\r\n} from '../../../../services';\r\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\r\nimport { useLogger } from '../../../../services/logger/Logger';\r\nimport { NotificationService } from '../../../../services/notification/notification-service';\r\nimport { normalizeNullOrUndefined } from '../../../../utils/general';\r\nimport { nameof } from '../../../../utils/nameof';\r\nimport { areTrimmedStringsEqual, doesStringExistInOtherString } from '../../../../utils/strings';\r\nimport { generateUuid, isValidUuid } from '../../../../utils/uuid';\r\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport FeeTable from '../../../common-page-components/fee-table/FeeTable';\r\nimport { FloatingLoadingIndicatorContext } from '../../../common-page-components/floating-loading-indicator/FloatingLoadingIndicatorContext';\r\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\r\nimport { BTGeneralContext } from '../../../common-page-components/general-contexts/BTGeneralContext';\r\nimport BTGridContainer, {\r\n GridRerenderTrigger,\r\n} from '../../../common-page-components/grid/grid-container/BTGridContainer';\r\nimport { BTGridContainerContextProvider } from '../../../common-page-components/grid/grid-container/BTGridContainerContext';\r\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport BTModal from '../../../common-page-components/modal/BTModal';\r\nimport BTNotes from '../../../common-page-components/notes/BTNotes';\r\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport useCommandServiceHelper from '../../../shared-page-components/hooks/useCommandServiceHelper';\r\nimport useDegradedActionNotifications from '../../../shared-page-components/hooks/useDegradedActionNotifications';\r\nimport useProject_Info from '../../../shared-page-components/hooks/useProject_Info';\r\nimport './BidSummaryPage.scss';\r\nimport useBidSummaryPageContext, { BidSummaryPageContextProvider } from './BidSummaryPageContext';\r\nimport BidSummaryKeyboardShortcuts from './components/BidSummaryKeyboardShortcuts';\r\nimport useFeeTable from './hooks/fees/useFeeTable';\r\nimport useBidSummary_Settings_ProjectBiddersRangesModal from './hooks/settings/useBidSummary_Settings_ProjectBiddersRangesModal';\r\nimport useBidSummary from './hooks/useBidSummary';\r\nimport useBidSummaryGrid from './hooks/useBidSummaryGrid';\r\nimport useBidSummaryPageHeader from './hooks/useBidSummaryPageHeader';\r\nimport useBidSummary_Alternates from './hooks/useBidSummary_Alternates';\r\nimport useBidSummary_ChangeNotifications from './hooks/useBidSummary_ChangeNotifications';\r\n\r\nexport interface BidSummaryOptions {\r\n displayAssignedToColumn: boolean;\r\n displayClassifications: boolean;\r\n displayAnalysis: boolean;\r\n displayNotes: boolean;\r\n}\r\n\r\ninterface RouteParams {\r\n projectId: string;\r\n}\r\n\r\ninterface BidSummaryPageNotification {\r\n type: 'project' | 'bid package' | 'settings';\r\n notification: DataChangedNotificationMessage | EntityFrozenNotificationMessage;\r\n}\r\n\r\nconst BidPackagePageInternalComponent: React.FC = () => {\r\n const history = useHistory();\r\n\r\n const { t } = useTranslation();\r\n\r\n const [liveUpdateRegistrationFailed, setLiveUpdateRegistrationFailed] = useState(false);\r\n\r\n const {\r\n alternateChange$,\r\n bidAmountBlur$,\r\n bidAmountChange$,\r\n bidSummaryDisplayOptionsChange$,\r\n contingencyBlur$,\r\n contingencyChange$,\r\n feeAmountBlur$,\r\n feeAmountChange$,\r\n feeCalculationRequest$,\r\n feesEdit$,\r\n keyboardShortcutsShow$,\r\n projectClose$,\r\n projectEditBiddersRanges$,\r\n projectEditNotes$,\r\n projectExportExcel$,\r\n projectShowInfo$,\r\n } = useBidSummaryPageContext();\r\n\r\n const logger = useLogger();\r\n\r\n const { showSuccessNotification, showErrorNotification, showInfoNotification } = useContext(\r\n NotificationPanelContext,\r\n );\r\n\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n\r\n const { showFloatingLoadingIndicator_Green, hideFloatingLoadingIndicator_Green } = useContext(\r\n FloatingLoadingIndicatorContext,\r\n );\r\n\r\n const routeParams = useParams();\r\n\r\n const { pageScroll_Y$, signalRResponseTimeout } = useContext(BTGeneralContext);\r\n\r\n const {\r\n onChangeCallback_BidAmount,\r\n onBlurCallback_BidAmount,\r\n\r\n onChangeCallback_Contingency,\r\n onBlurCallback_Contingency,\r\n\r\n successFunction_BidAmount,\r\n errorFunction_BidAmount,\r\n\r\n successFunction_Contingency,\r\n errorFunction_Contingency,\r\n } = useBidSummary();\r\n\r\n const [pageIsScrolled_Y, setPageIsScrolled_Y] = useState(false);\r\n\r\n const [keyboardShortcutsInfoIsOpen, setKeyboardShortcutsInfoIsOpen] = useState(false);\r\n\r\n const [gridRerenderTriggerObject, setGridRerenderTriggerObject] = useState(\r\n {},\r\n );\r\n\r\n const [feesTableKey, setFeesTableKey] = useState(generateUuid());\r\n\r\n const [gridSections, setGridSections] = useState([]);\r\n\r\n const [bidSummaryOptions, setBidSummaryOptions] = useState({\r\n displayAssignedToColumn: true,\r\n displayClassifications: true,\r\n displayAnalysis: true,\r\n displayNotes: true,\r\n });\r\n\r\n const [isInitialDataLoadComplete, setIsInitialDataLoadComplete] = useState(false);\r\n\r\n const notificationsReceivedDuringInitialDataLoad = useRef([]);\r\n\r\n const [bidPackages, setBidPackages] = useState([]);\r\n const bidPackages_Staging = useRef([]);\r\n const bidPackages_Committed = useRef([]);\r\n\r\n const [alternates, setAlternates] = useState([]);\r\n const alternates_Staging = useRef([]);\r\n const alternates_Committed = useRef([]);\r\n\r\n const [projectInfo, setProjectInfo] = useState();\r\n const [projectImageBlobUrl, setProjectImageBlobUrl] = useState(null);\r\n const [projectFees, setProjectFees] = useState([]);\r\n const [projectPreferences, setProjectPreferences] = useState();\r\n const [notesModalIsOpen, setNotesModalIsOpen] = useState(false);\r\n const [feesModalIsOpen, setFeesModalIsOpen] = useState(false);\r\n\r\n // These ref variables are copies of things that we can operate on in SignalR change handlers, in cases\r\n // where multiple handlers are running \"concurrently\" (ie. one is awaiting an AJAX call and another starts).\r\n // Relying on a state variable leads us to have stale data in this situation (yay, React).\r\n const alternatesToUpdateFromSignalRHandler = useRef([]);\r\n const bidPackagesToUpdateFromSignalRHandler = useRef([]);\r\n const detailProjectInfoToUpdateFromSignalRHandler = useRef();\r\n const feesToUpdateFromSignalRHandler = useRef([]);\r\n\r\n // A copy of the fees that contains \"committed\" data\r\n const projectFees_Committed = useRef([]);\r\n\r\n // The current project image name\r\n const currentProjectImageUri = useRef();\r\n\r\n const [bidDayApplicationEntityIsFrozen, setBidDayApplicationEntityIsFrozen] = useState(\r\n false,\r\n );\r\n const [systemSettingsEntityIsFrozen, setSystemSettingsEntityIsFrozen] = useState(false);\r\n const [projectIsFrozen, setProjectIsFrozen] = useState(false);\r\n const [projectNotesAreFrozen, setProjectNotesAreFrozen] = useState(false);\r\n const [bidPackageIdsThatAreFrozen, setBidPackageIdsThatAreFrozen] = useState([]);\r\n const [adjustmentNoteIdsThatAreFrozen, setAdjustmentNoteIdsThatAreFrozen] = useState(\r\n [],\r\n );\r\n\r\n const [bidSummaryPageHeader, setBidSummaryPageHeader] = useState();\r\n\r\n const [signalRBroadcast_BidPackage$, onSignalRBroadcast_BidPackage] = useObservableWithValue<\r\n DataChangedNotificationMessage | EntityFrozenNotificationMessage\r\n >();\r\n const [signalRBroadcast_Project$, onSignalRBroadcast_Project] = useObservableWithValue<\r\n DataChangedNotificationMessage | EntityFrozenNotificationMessage\r\n >();\r\n const [signalRBroadcast_Settings$, onSignalRBroadcast_Settings] = useObservableWithValue<\r\n DataChangedNotificationMessage | EntityFrozenNotificationMessage\r\n >();\r\n\r\n const isProjectAdmin = useMemo(\r\n () =>\r\n doesStringExistInOtherString(\r\n projectInfo?.projectAdmins,\r\n AuthenticationService.currentUserInfo!.email,\r\n ),\r\n [projectInfo?.projectAdmins],\r\n );\r\n\r\n const isProjectContributor = useMemo(\r\n () =>\r\n doesStringExistInOtherString(\r\n projectInfo?.contributors,\r\n AuthenticationService.currentUserInfo!.email,\r\n ),\r\n [projectInfo?.contributors],\r\n );\r\n\r\n const projectIsClosed = useMemo((): boolean => projectInfo?.isClosed ?? false, [\r\n projectInfo?.isClosed,\r\n ]);\r\n\r\n const isReadOnly = useMemo((): boolean => {\r\n if (liveUpdateRegistrationFailed) {\r\n return true;\r\n }\r\n\r\n // If the project is frozen or in a closed state, set read-only\r\n if (projectIsClosed || projectIsFrozen) {\r\n return true;\r\n }\r\n\r\n // If the user is not a project admin, set read-only\r\n if (!isProjectAdmin) {\r\n return true;\r\n }\r\n return false;\r\n }, [liveUpdateRegistrationFailed, projectIsClosed, projectIsFrozen, isProjectAdmin]);\r\n\r\n const projectHasFeeCalculationFailure = useMemo(\r\n (): boolean => projectInfo?.hasFeeCalculationFailure ?? false,\r\n [projectInfo?.hasFeeCalculationFailure],\r\n );\r\n\r\n const { executeCommand } = useCommandServiceHelper();\r\n\r\n // A ref variable to maintain the current value of the source ID's so we can tell when things changed\r\n const bidPackageIdsForChangeNotifications_CurrValue = useRef([]);\r\n\r\n // A ref variable to maintain a running list of source ID's we registered for notifications with\r\n const currentlyRegisteredBidPackageSourceIds = useRef([]);\r\n\r\n const bidPackageIdsForChangeNotifications = useMemo(() => {\r\n const bidPackageIds = bidPackages.map((bp) => bp.id);\r\n const bidPackageNoteIds = bidPackages.map((bp) => bp.notesId || '').filter((v) => v);\r\n const bidPackageAdjustmentNoteIds = bidPackages\r\n .flatMap((bp) => bp.adjustments.map((v) => v.notesId || ''))\r\n .filter((v) => v);\r\n\r\n const idsToRegisterForNotifications = sortBy(\r\n [...bidPackageIds, ...bidPackageNoteIds, ...bidPackageAdjustmentNoteIds],\r\n (v) => v,\r\n );\r\n\r\n if (\r\n isEqual(idsToRegisterForNotifications, bidPackageIdsForChangeNotifications_CurrValue.current)\r\n ) {\r\n return bidPackageIdsForChangeNotifications_CurrValue.current;\r\n }\r\n\r\n bidPackageIdsForChangeNotifications_CurrValue.current = idsToRegisterForNotifications;\r\n\r\n return idsToRegisterForNotifications;\r\n }, [bidPackages]);\r\n\r\n // A ref variable to maintain the current value of the source ID's so we can tell when things changed\r\n const projectIdsForChangeNotifications_CurrValue = useRef([]);\r\n\r\n // A ref variable to maintain a running list of source ID's we registered for notifications with\r\n const currentlyRegisteredProjectSourceIds = useRef([]);\r\n\r\n const projectIdsForChangeNotifications = useMemo(() => {\r\n if (!projectInfo) {\r\n return projectIdsForChangeNotifications_CurrValue.current;\r\n }\r\n\r\n const idsToWatch = [projectInfo.id];\r\n\r\n if (projectInfo?.notesId) {\r\n idsToWatch.push(projectInfo.notesId);\r\n }\r\n\r\n if (isEqual(idsToWatch, projectIdsForChangeNotifications_CurrValue.current)) {\r\n return projectIdsForChangeNotifications_CurrValue.current;\r\n }\r\n\r\n projectIdsForChangeNotifications_CurrValue.current = idsToWatch;\r\n\r\n return idsToWatch;\r\n }, [projectInfo]);\r\n\r\n const { projectChangeHandler, bidPackageChangeHandler } = useBidSummary_ChangeNotifications();\r\n\r\n const {\r\n onChangeCallback_Alternate,\r\n createAlternateUpdateCommand,\r\n successFunction_Alternate,\r\n errorFunction_Alternate,\r\n } = useBidSummary_Alternates();\r\n\r\n const {\r\n feeTableFees,\r\n addFeeCallback,\r\n deleteFeeCallback,\r\n updateFeeCallback,\r\n onSortEndCallback,\r\n calculateFeesCallback,\r\n onSaveClick,\r\n discardCallback,\r\n setFeeTableFeesNeedToBeCalculated,\r\n } = useFeeTable(isProjectAdmin, projectInfo?.id ?? '', projectFees, bidPackages, alternates);\r\n\r\n // #region Hook Callbacks\r\n\r\n // handles submitting the command for the changes to the project bidders ranges\r\n const onProjectBiddersRangesSubmitClick = useCallback(\r\n async (\r\n newProjectBiddersRanges: ProjectBiddersRanges,\r\n commandToExecute: ICommand,\r\n ): Promise => {\r\n let result = false;\r\n if (!projectPreferences) {\r\n logger.logError(\r\n new Error(\r\n \"Unable to continue with committing the changes to the project's bidders ranges. The page is missing the existing project preferences.\",\r\n ),\r\n );\r\n\r\n showErrorNotification(t('general:error'), t('bid-summary:updateProjectBiddersRangesError'));\r\n return result;\r\n }\r\n\r\n result = await executeCommand({\r\n commandToExecute: commandToExecute,\r\n commandExecutionType: 'page-loading-overlay',\r\n commandSuccessCallback: () => {\r\n // Update the preferences with the latest ranges so the UI is up to date immediately,\r\n // regardless of any SignalR events\r\n setProjectPreferences({\r\n ...projectPreferences,\r\n lowBiddersMax: newProjectBiddersRanges.lowBiddersMax,\r\n midBiddersMax: newProjectBiddersRanges.midBiddersMax,\r\n });\r\n },\r\n commandErrorCallback: () => {\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n },\r\n customErrorMessage: t('bid-summary:updateProjectBiddersRangesError'),\r\n });\r\n\r\n return result;\r\n },\r\n [projectPreferences, showErrorNotification, executeCommand, t, history, logger],\r\n );\r\n\r\n // #endregion\r\n\r\n // #region Child Hooks\r\n\r\n // Project Number of Bidders Ranges hook\r\n const {\r\n setCurrentProjectBiddersRangesModalState,\r\n getProjectBiddersRangesModalJSX,\r\n } = useBidSummary_Settings_ProjectBiddersRangesModal({\r\n projectId: projectInfo?.id,\r\n onSubmitClickCallback: onProjectBiddersRangesSubmitClick,\r\n });\r\n\r\n // #endregion\r\n\r\n // #region Main Hooks\r\n\r\n const { generateBidSummaryPageHeader } = useBidSummaryPageHeader();\r\n\r\n const { generateSummaryGridSections } = useBidSummaryGrid({\r\n bidSummaryOptions,\r\n isReadOnly,\r\n isProjectAdmin,\r\n isProjectContributor,\r\n isProjectFrozen: projectIsFrozen,\r\n projectHasFeeCalculationFailure,\r\n bidPackages,\r\n projectFees,\r\n alternates,\r\n projectPreferences: projectPreferences!,\r\n frozenBidPackageIds: bidPackageIdsThatAreFrozen,\r\n frozenBidPackageAdjustmentNoteIds: adjustmentNoteIdsThatAreFrozen,\r\n });\r\n\r\n // #endregion\r\n\r\n const { getProjectInfoJSX, showProjectInfo } = useProject_Info();\r\n\r\n const saveProjectNotes = useCallback(\r\n async (newNotes: string): Promise => {\r\n if (!projectInfo) {\r\n return;\r\n }\r\n\r\n newNotes = newNotes.trim();\r\n const response = await executeCommand({\r\n commandToExecute: new AddEditProjectNotesToProjectCommand(\r\n projectInfo.id,\r\n projectInfo.notesId,\r\n newNotes.trim(),\r\n ),\r\n commandExecutionType: 'relies-on-signal-r-for-completion',\r\n customErrorMessage: t('bid-summary:errorAddNotes'),\r\n });\r\n\r\n if (response) {\r\n showSuccessNotification(t('general:success'), t('bid-summary:successSetNotes'));\r\n }\r\n\r\n setProjectInfo((curr) => {\r\n if (!curr) {\r\n return curr;\r\n }\r\n\r\n return {\r\n ...curr,\r\n notes: newNotes,\r\n };\r\n });\r\n setNotesModalIsOpen(false);\r\n },\r\n [projectInfo, executeCommand, showSuccessNotification, t],\r\n );\r\n\r\n const onNotesClose = useCallback(\r\n (notes: string): void => {\r\n const sanitizedNotes = notes.trim();\r\n if (!sanitizedNotes || sanitizedNotes === projectInfo?.notes?.trim()) {\r\n setNotesModalIsOpen(false);\r\n return;\r\n }\r\n\r\n showConfirmationOverlay({\r\n text: t('general:discardConfirmation'),\r\n buttons: [\r\n {\r\n text: t('general:discard'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n setNotesModalIsOpen(false);\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:cancel'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n },\r\n [projectInfo?.notes, showConfirmationOverlay, t, hideConfirmationOverlay],\r\n );\r\n\r\n const onNotesModalClose = useCallback(() => {\r\n setNotesModalIsOpen(false);\r\n }, []);\r\n\r\n const downloadProjectExport = useCallback(async () => {\r\n if (projectInfo) {\r\n showConfirmationOverlay({\r\n text: t('project:exportConfirmation'),\r\n image: 'excel',\r\n buttons: [\r\n {\r\n text: t('general:export'),\r\n onClick: async (): Promise => {\r\n hideConfirmationOverlay();\r\n\r\n showPageLoadingOverlay();\r\n\r\n try {\r\n await ProjectApi.exportProjectToExcel(projectInfo.id);\r\n } catch (error) {\r\n logger.logError(error);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:cancel'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n }\r\n }, [\r\n projectInfo,\r\n showConfirmationOverlay,\r\n t,\r\n hideConfirmationOverlay,\r\n showPageLoadingOverlay,\r\n logger,\r\n hidePageLoadingOverlay,\r\n ]);\r\n\r\n const projectNotificationHandler = useCallback(\r\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\r\n try {\r\n showFloatingLoadingIndicator_Green(t('general:syncing'));\r\n\r\n // If the project is frozen, set the frozen flag and exit\r\n if (message.hasOwnProperty(nameof('IsFrozen'))) {\r\n logger.logDebug(`project.onFrozenEntityNotification: ${JSON.stringify(message)}`);\r\n const entityFrozenMessage = message as EntityFrozenNotificationMessage;\r\n\r\n if (entityFrozenMessage.IsFrozen) {\r\n // Set frozen entities in state\r\n if (entityFrozenMessage.SourceId === projectInfo!.id.toLowerCase()) {\r\n setProjectIsFrozen(true);\r\n } else if (entityFrozenMessage.SourceId === projectInfo!.notesId?.toLowerCase()) {\r\n setProjectNotesAreFrozen(true);\r\n }\r\n } else {\r\n // TODO: Unfreeze entities\r\n // NOTE: As-is we have no way to send an \"unfrozen\" message so there's no way to test\r\n }\r\n return;\r\n }\r\n\r\n logger.logDebug(`project.onDataChanged: ${JSON.stringify(message)}`);\r\n const messageAsDataChangedMessage = message as DataChangedNotificationMessage;\r\n\r\n // If the assigned to user ID was set on a newly added bid package, we need to get user objects\r\n // from the server so the change handler code can set things appropriately.\r\n // NOTE: We only need to check the \"Added\" collection here.\r\n const messagesWithAssignedToUserIdChange = messageAsDataChangedMessage.Added.filter(\r\n (v) => v.Values[nameof('assignedToUserId')] !== undefined,\r\n ).map((v) => v.Values[nameof('assignedToUserId')] as string);\r\n\r\n const usersArray: User[] = [];\r\n\r\n if (messagesWithAssignedToUserIdChange.length > 0) {\r\n const results = await Promise.all(\r\n messagesWithAssignedToUserIdChange.map((v) => UserApi.getUserById(v)),\r\n );\r\n usersArray.push(...results.filter((v) => v !== null).map((v) => v!));\r\n }\r\n\r\n const {\r\n bidPackages: updatedBidPackages,\r\n projectInfo: updatedProjectInfo,\r\n alternates: updatedAlternates,\r\n fees: updatedProjectFees,\r\n } = projectChangeHandler(\r\n messageAsDataChangedMessage,\r\n detailProjectInfoToUpdateFromSignalRHandler.current!,\r\n bidPackagesToUpdateFromSignalRHandler.current,\r\n alternatesToUpdateFromSignalRHandler.current,\r\n // NOTE: For some reason, the current value of projectFees fluctuates between current and old values in this particular handler,\r\n // even though the state variable is up to date.\r\n // The projectFees_Copy has up to date data that does not change, so we pass that to the change handler.\r\n feesToUpdateFromSignalRHandler.current,\r\n usersArray,\r\n );\r\n\r\n bidPackagesToUpdateFromSignalRHandler.current = updatedBidPackages;\r\n detailProjectInfoToUpdateFromSignalRHandler.current = updatedProjectInfo;\r\n alternatesToUpdateFromSignalRHandler.current = updatedAlternates;\r\n feesToUpdateFromSignalRHandler.current = updatedProjectFees;\r\n\r\n // Set the state for what we can as soon as we can, without waiting for any additional AJAX calls\r\n setProjectInfo(cloneDeep(detailProjectInfoToUpdateFromSignalRHandler.current));\r\n setProjectFees(cloneDeep(feesToUpdateFromSignalRHandler.current));\r\n setAlternates(cloneDeep(alternatesToUpdateFromSignalRHandler.current));\r\n\r\n projectFees_Committed.current = cloneDeep(feesToUpdateFromSignalRHandler.current);\r\n\r\n // When alternates are updated, we need to pull updated contingency amounts\r\n if (\r\n messageAsDataChangedMessage.Updated.some(\r\n (v) => (v.Type as DataChangedEntryTypes_BidSummaryPage) === 'Alternate',\r\n )\r\n ) {\r\n const result = await BidPackageApi.getBidPackageContingencyAmounts(\r\n bidPackages.map((v) => v.id),\r\n );\r\n\r\n const updateBidPackagesContingencyAmount = (\r\n bidPackagesToUpdate: BidPackage[],\r\n ): BidPackage[] => {\r\n const copy = [...bidPackagesToUpdate];\r\n copy.forEach((v) => {\r\n v.contingencyAmount = clone(\r\n result.find((m) => m?.bidPackageId === v.id) ?? v.contingencyAmount,\r\n );\r\n });\r\n\r\n return copy;\r\n };\r\n\r\n bidPackagesToUpdateFromSignalRHandler.current = updateBidPackagesContingencyAmount(\r\n bidPackagesToUpdateFromSignalRHandler.current,\r\n );\r\n\r\n bidPackages_Staging.current = updateBidPackagesContingencyAmount(\r\n bidPackages_Staging.current,\r\n );\r\n\r\n bidPackages_Committed.current = updateBidPackagesContingencyAmount(\r\n bidPackages_Committed.current,\r\n );\r\n }\r\n\r\n // Set the bid packages, after updating things from the results of the AJAX call\r\n setBidPackages(cloneDeep(bidPackagesToUpdateFromSignalRHandler.current));\r\n\r\n // Refresh the grid when certain things happen that can affect the rows or columns we display\r\n if (\r\n messageAsDataChangedMessage.Added.concat(messageAsDataChangedMessage.Deleted)\r\n .concat(messageAsDataChangedMessage.Updated)\r\n .some((v) => (dataChangeEntryTypesThatCanAffectGrid as string[]).includes(v.Type))\r\n ) {\r\n setGridRerenderTriggerObject({\r\n rowsChanged: true,\r\n primaryGridColumnsChanged: false,\r\n });\r\n }\r\n\r\n // Update the fee information for the fee table modal, if fees have changed since the initial data load.\r\n if (\r\n messageAsDataChangedMessage.Added.concat(messageAsDataChangedMessage.Updated)\r\n .concat(messageAsDataChangedMessage.Deleted)\r\n .some((v) => (v.Type as DataChangedEntryTypes_BidSummaryPage) === 'Fee')\r\n ) {\r\n setFeeTableFeesNeedToBeCalculated(true);\r\n }\r\n\r\n if (\r\n messageAsDataChangedMessage.Added.concat(messageAsDataChangedMessage.Updated)\r\n .concat(messageAsDataChangedMessage.Deleted)\r\n .some((v) => v.Type === ('Preference' as DataChangedEntryTypes_BidSummaryPage))\r\n ) {\r\n // When preferences change, we want to pull them again from the API, since the API\r\n // converts them into a custom data structure for use with this code\r\n const updatedPreferences = await PreferencesApi.getPreferences(projectInfo!.id);\r\n setProjectPreferences(updatedPreferences);\r\n }\r\n\r\n // If the message was triggered by something the current user did and we have an active\r\n // signal R response timeout, it means we are waiting for a SignalR event for whatever we just did\r\n if (\r\n areTrimmedStringsEqual(\r\n messageAsDataChangedMessage.ChangedBy,\r\n AuthenticationService.currentUserInfo?.email,\r\n )\r\n ) {\r\n if (signalRResponseTimeout.current) {\r\n clearTimeout(signalRResponseTimeout.current);\r\n signalRResponseTimeout.current = null;\r\n\r\n hidePageLoadingOverlay(true);\r\n }\r\n }\r\n } finally {\r\n // Delay turning off the loading indicator slightly, since this code can run very fast at times\r\n // and we don't want things to flicker too fast where the user doesn't see it (it's beautiful and\r\n // deserves to be seen, dammit)\r\n setTimeout(() => {\r\n hideFloatingLoadingIndicator_Green();\r\n }, 500);\r\n }\r\n },\r\n [\r\n bidPackages,\r\n hideFloatingLoadingIndicator_Green,\r\n hidePageLoadingOverlay,\r\n logger,\r\n projectChangeHandler,\r\n projectInfo,\r\n setFeeTableFeesNeedToBeCalculated,\r\n showFloatingLoadingIndicator_Green,\r\n signalRResponseTimeout,\r\n t,\r\n ],\r\n );\r\n\r\n const bidPackageNotificationHandler = useCallback(\r\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\r\n try {\r\n showFloatingLoadingIndicator_Green(t('general:syncing'));\r\n\r\n const bidPackageIds = bidPackages.map((bp) => bp.id.toLowerCase());\r\n\r\n // If a bid package is frozen, set the frozen flag and exit\r\n if (message.hasOwnProperty(nameof('IsFrozen'))) {\r\n logger.logDebug(`bidPackage.onFrozenEntityNotification: ${JSON.stringify(message)}`);\r\n const entityFrozenMessage = message as EntityFrozenNotificationMessage;\r\n\r\n const bidPackageAdjustmentNoteIds = bidPackages\r\n .flatMap((v) => v.adjustments.map((v) => v.notesId?.toLowerCase() || ''))\r\n .filter((v) => v);\r\n\r\n if (entityFrozenMessage.IsFrozen) {\r\n // Set frozen entities in state\r\n if (bidPackageIds.includes(entityFrozenMessage.SourceId)) {\r\n setBidPackageIdsThatAreFrozen((v) => [...v, entityFrozenMessage.SourceId]);\r\n } else if (bidPackageAdjustmentNoteIds.includes(entityFrozenMessage.SourceId)) {\r\n setAdjustmentNoteIdsThatAreFrozen((v) => [...v, entityFrozenMessage.SourceId]);\r\n }\r\n } else {\r\n // TODO: Unfreeze entities\r\n // NOTE: As-is we have no way to send an \"unfrozen\" message so there's no way to test\r\n }\r\n\r\n return;\r\n }\r\n\r\n const messageAsDataChangedMessage = message as DataChangedNotificationMessage;\r\n\r\n logger.logDebug(`bidPackage.onDataChange: ${JSON.stringify(messageAsDataChangedMessage)}`);\r\n\r\n let updatedBidPackageTotals: BidPackage | null = null;\r\n\r\n // If the message for for a bid package and not another another entity type, get updated totals\r\n if (bidPackageIds.includes(messageAsDataChangedMessage.SourceId)) {\r\n updatedBidPackageTotals = (await BidSummaryApi.getBidPackageTotals(\r\n messageAsDataChangedMessage.SourceId,\r\n ))!;\r\n }\r\n\r\n // If the assigned to user ID changed, we need to get user objects from the server so the change handler\r\n // code can set things appropriately.\r\n // NOTE: We only need to check the \"Updated\" collection here.\r\n const messagesWithAssignedToUserIdChange = messageAsDataChangedMessage.Updated.filter(\r\n (v) => v.Values[nameof('assignedToUserId')] !== undefined,\r\n ).map((v) => v.Values[nameof('assignedToUserId')] as string);\r\n\r\n const usersArray: User[] = [];\r\n\r\n if (messagesWithAssignedToUserIdChange.length > 0) {\r\n const results = await Promise.all(\r\n messagesWithAssignedToUserIdChange.map((v) => UserApi.getUserById(v)),\r\n );\r\n usersArray.push(...results.filter((v) => v !== null).map((v) => v!));\r\n }\r\n\r\n const { bidPackages: updatedBidPackages } = bidPackageChangeHandler(\r\n messageAsDataChangedMessage,\r\n detailProjectInfoToUpdateFromSignalRHandler.current!,\r\n bidPackagesToUpdateFromSignalRHandler.current,\r\n alternatesToUpdateFromSignalRHandler.current,\r\n // NOTE: For some reason, the current value of projectFees fluctuates between current and old values in this particular handler,\r\n // even though the state variable is up to date.\r\n // The projectFees_Copy has up to date data that does not change, so we pass that to the change handler.\r\n feesToUpdateFromSignalRHandler.current,\r\n updatedBidPackageTotals,\r\n usersArray,\r\n );\r\n\r\n const { bidPackages: updatedBidPackages_Staging } = bidPackageChangeHandler(\r\n messageAsDataChangedMessage,\r\n detailProjectInfoToUpdateFromSignalRHandler.current!,\r\n bidPackages_Staging.current,\r\n alternatesToUpdateFromSignalRHandler.current,\r\n projectFees_Committed.current,\r\n updatedBidPackageTotals,\r\n usersArray,\r\n );\r\n\r\n const { bidPackages: updatedBidPackages_Committed } = bidPackageChangeHandler(\r\n messageAsDataChangedMessage,\r\n detailProjectInfoToUpdateFromSignalRHandler.current!,\r\n bidPackages_Committed.current,\r\n alternatesToUpdateFromSignalRHandler.current,\r\n projectFees_Committed.current,\r\n updatedBidPackageTotals,\r\n usersArray,\r\n );\r\n\r\n // Update the ref variables before we make the AJAX call, so any other instances of this code that may run\r\n // in the meantime can reference the ref variables for up-to-date data\r\n bidPackagesToUpdateFromSignalRHandler.current = updatedBidPackages;\r\n bidPackages_Staging.current = updatedBidPackages_Staging;\r\n bidPackages_Committed.current = updatedBidPackages_Committed;\r\n\r\n // When bid packages are updated, we need to pull updated contingency amounts\r\n const bidPackageIdsThatAffectContingency = uniq([\r\n ...messageAsDataChangedMessage.Updated.filter(\r\n (v) => (v.Type as DataChangedEntryTypes_BidSummaryPage) === 'BidPackage',\r\n ).map((v) => v.Values[nameof('id')] as string),\r\n\r\n // When adjustments on bid package totals are added/updated/deleted, we also need to pull updated contingency amounts.\r\n ...messageAsDataChangedMessage.Added.concat(messageAsDataChangedMessage.Updated)\r\n .concat(messageAsDataChangedMessage.Deleted)\r\n .filter((v) => (v.Type as DataChangedEntryTypes_BidSummaryPage) === 'Adjustment')\r\n .map((v) => v.Values[nameof('bidPackageId')] as string),\r\n ]);\r\n\r\n // Create a variable that we can reassign as we call code to update it\r\n\r\n if (bidPackageIdsThatAffectContingency.length > 0) {\r\n const result = await BidPackageApi.getBidPackageContingencyAmounts(\r\n bidPackageIdsThatAffectContingency,\r\n );\r\n\r\n const updateBidPackagesContingencyAmount = (\r\n bidPackagesToUpdate: BidPackage[],\r\n ): BidPackage[] => {\r\n const copy = [...bidPackagesToUpdate];\r\n\r\n copy.forEach((v) => {\r\n v.contingencyAmount = clone(\r\n result.find((m) => m?.bidPackageId === v.id) ?? v.contingencyAmount,\r\n );\r\n });\r\n\r\n return copy;\r\n };\r\n\r\n // Apply the updated contingency amounts to the bid package collections\r\n bidPackagesToUpdateFromSignalRHandler.current = updateBidPackagesContingencyAmount(\r\n bidPackagesToUpdateFromSignalRHandler.current,\r\n );\r\n\r\n bidPackages_Staging.current = updateBidPackagesContingencyAmount(\r\n bidPackages_Staging.current,\r\n );\r\n\r\n bidPackages_Committed.current = updateBidPackagesContingencyAmount(\r\n bidPackages_Committed.current,\r\n );\r\n }\r\n\r\n // NOTE: We only want to update bid packages in this SignalR handler, we don't want to touch project related things (ie. everything else)\r\n setBidPackages(cloneDeep(bidPackagesToUpdateFromSignalRHandler.current));\r\n\r\n if (\r\n messageAsDataChangedMessage.Added.some((v) =>\r\n (dataChangeEntryTypesThatCanAffectGrid as string[]).includes(v.Type),\r\n ) ||\r\n messageAsDataChangedMessage.Deleted.some((v) =>\r\n (dataChangeEntryTypesThatCanAffectGrid as string[]).includes(v.Type),\r\n )\r\n ) {\r\n setGridRerenderTriggerObject({\r\n rowsChanged: true,\r\n primaryGridColumnsChanged: false,\r\n });\r\n }\r\n } finally {\r\n // Delay turning off the loading indicator slightly, since this code can run very fast at times\r\n // and we don't want things to flicker too fast where the user doesn't see it (it's beautiful and\r\n // deserves to be seen, dammit)\r\n setTimeout(() => {\r\n hideFloatingLoadingIndicator_Green();\r\n }, 500);\r\n }\r\n },\r\n [\r\n bidPackageChangeHandler,\r\n bidPackages,\r\n hideFloatingLoadingIndicator_Green,\r\n logger,\r\n showFloatingLoadingIndicator_Green,\r\n t,\r\n ],\r\n );\r\n\r\n const systemSettingsNotificationHandler = useCallback(\r\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\r\n try {\r\n showFloatingLoadingIndicator_Green(t('general:syncing'));\r\n\r\n // If the project is frozen, set the frozen flag and exit\r\n if (message.hasOwnProperty(nameof('IsFrozen'))) {\r\n logger.logDebug(`bidDay.onFrozenEntityNotification: ${JSON.stringify(message)}`);\r\n const entityFrozenMessage = message as EntityFrozenNotificationMessage;\r\n\r\n if (entityFrozenMessage.IsFrozen) {\r\n // Set frozen entities in state\r\n if (\r\n entityFrozenMessage.SourceId ===\r\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION.toLowerCase()\r\n ) {\r\n setBidDayApplicationEntityIsFrozen(true);\r\n } else if (\r\n entityFrozenMessage.SourceId ===\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS.toLowerCase()\r\n ) {\r\n setSystemSettingsEntityIsFrozen(true);\r\n }\r\n } else {\r\n // TODO: Unfreeze entities\r\n // NOTE: As-is we have no way to send an \"unfrozen\" message so there's no way to test\r\n }\r\n return;\r\n }\r\n } finally {\r\n // Delay turning off the loading indicator slightly, since this code can run very fast at times\r\n // and we don't want things to flicker too fast where the user doesn't see it (it's beautiful and\r\n // deserves to be seen, dammit)\r\n setTimeout(() => {\r\n hideFloatingLoadingIndicator_Green();\r\n }, 500);\r\n }\r\n },\r\n [hideFloatingLoadingIndicator_Green, logger, showFloatingLoadingIndicator_Green, t],\r\n );\r\n\r\n const loadInitialData = useCallback(async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n if (!routeParams.projectId || !isValidUuid(routeParams.projectId)) {\r\n throw new Error(t('bid-summary:invalidParameter_ProjectId'));\r\n }\r\n\r\n const projectInfo = await ProjectApi.getProjectInfoById(routeParams.projectId);\r\n\r\n if (!projectInfo) {\r\n throw new Error(t('bid-summary:projectNotFound'));\r\n }\r\n\r\n setProjectInfo(projectInfo);\r\n detailProjectInfoToUpdateFromSignalRHandler.current = cloneDeep(projectInfo);\r\n\r\n const [bidPackages, alternates, fees, preferences] = await Promise.all([\r\n BidSummaryApi.getBidPackagesByProjectId(projectInfo.id),\r\n BidSummaryApi.getAlternatesByProjectId(projectInfo.id),\r\n ProjectApi.getFeesAndTotalsByProjectId(projectInfo.id),\r\n PreferencesApi.getPreferences(projectInfo.id),\r\n ]);\r\n\r\n // Get the frozen status of the bid day application\r\n const bidDayApplicationEntityIsFrozenResult = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION,\r\n );\r\n\r\n setBidDayApplicationEntityIsFrozen(bidDayApplicationEntityIsFrozenResult);\r\n\r\n // Get the frozen status of the system settings\r\n const systemSettingsEntityIsFrozenResult = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n );\r\n\r\n setSystemSettingsEntityIsFrozen(systemSettingsEntityIsFrozenResult);\r\n\r\n const [projectIsFrozen, projectNotesAreFrozen] = await Promise.all([\r\n FrozenEntitiesApi.checkIfEntityIsFrozen(routeParams.projectId),\r\n projectInfo?.notesId\r\n ? FrozenEntitiesApi.checkIfEntityIsFrozen(projectInfo.notesId)\r\n : Promise.resolve(false),\r\n ]);\r\n\r\n // Get the frozen status for any bid packages\r\n const bidPackageIds = bidPackages!.map((v) => v.id);\r\n const bidPackagesPromisesArray: Promise[] = bidPackageIds.map((v) =>\r\n FrozenEntitiesApi.checkIfEntityIsFrozen(v),\r\n );\r\n\r\n const bidPackagesFrozenResults = await Promise.all(bidPackagesPromisesArray);\r\n const frozenBidPackageIds: string[] = [];\r\n\r\n bidPackagesFrozenResults.forEach((v, i) => {\r\n if (v) {\r\n frozenBidPackageIds.push(bidPackageIds[i]);\r\n }\r\n });\r\n\r\n // Get the frozen status for any bid package adjustment notes\r\n const bidPackageAdjustmentNoteIds = bidPackages!.flatMap((v) =>\r\n v.adjustments.map((m) => m.notesId).filter((m) => m),\r\n ) as string[];\r\n\r\n const bidPackageAdjustmentNoteIdsPromisesArray: Promise<\r\n boolean\r\n >[] = bidPackageAdjustmentNoteIds.map((v) => FrozenEntitiesApi.checkIfEntityIsFrozen(v));\r\n\r\n const bidPackageAdjustmentNotesFrozenResults = await Promise.all(\r\n bidPackageAdjustmentNoteIdsPromisesArray,\r\n );\r\n const frozenBidPackageAdjustmentNoteIds: string[] = [];\r\n\r\n bidPackageAdjustmentNotesFrozenResults.forEach((v, i) => {\r\n if (v) {\r\n frozenBidPackageAdjustmentNoteIds.push(bidPackageAdjustmentNoteIds[i]);\r\n }\r\n });\r\n\r\n setProjectIsFrozen(projectIsFrozen);\r\n setProjectNotesAreFrozen(projectNotesAreFrozen);\r\n setBidPackageIdsThatAreFrozen(frozenBidPackageIds);\r\n setAdjustmentNoteIdsThatAreFrozen(frozenBidPackageAdjustmentNoteIds);\r\n\r\n setBidPackages(bidPackages || []);\r\n bidPackagesToUpdateFromSignalRHandler.current = cloneDeep(bidPackages || []);\r\n\r\n bidPackages_Staging.current = cloneDeep(bidPackages || []);\r\n bidPackages_Committed.current = cloneDeep(bidPackages || []);\r\n\r\n setProjectPreferences(preferences);\r\n\r\n const newProjectFees = sortBy(fees || [], (f) => f.order);\r\n\r\n setProjectFees(newProjectFees);\r\n projectFees_Committed.current = cloneDeep(newProjectFees);\r\n feesToUpdateFromSignalRHandler.current = cloneDeep(newProjectFees);\r\n\r\n setAlternates(alternates || []);\r\n alternatesToUpdateFromSignalRHandler.current = alternates ? cloneDeep(alternates) : [];\r\n alternates_Committed.current = alternates ? cloneDeep(alternates) : [];\r\n alternates_Staging.current = alternates ? cloneDeep(alternates) : [];\r\n\r\n // Refresh the grid\r\n setGridRerenderTriggerObject({\r\n rowsChanged: true,\r\n primaryGridColumnsChanged: true,\r\n });\r\n\r\n // Process any notifications we received during the initial data load\r\n for (const msg of notificationsReceivedDuringInitialDataLoad.current) {\r\n if (msg.type === 'project') {\r\n await projectNotificationHandler(msg.notification);\r\n } else if (msg.type === 'bid package') {\r\n await bidPackageNotificationHandler(msg.notification);\r\n } else if (msg.type === 'settings') {\r\n await systemSettingsNotificationHandler(msg.notification);\r\n }\r\n }\r\n notificationsReceivedDuringInitialDataLoad.current = [];\r\n\r\n setIsInitialDataLoadComplete(true);\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('bid-summary:loadBidSummaryError'));\r\n\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n }, [\r\n bidPackageNotificationHandler,\r\n hidePageLoadingOverlay,\r\n history,\r\n logger,\r\n projectNotificationHandler,\r\n routeParams.projectId,\r\n showErrorNotification,\r\n showPageLoadingOverlay,\r\n systemSettingsNotificationHandler,\r\n t,\r\n ]);\r\n\r\n useDegradedActionNotifications('BidSummaryPage');\r\n\r\n // Initial data load on mount\r\n useEffect(() => {\r\n loadInitialData();\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n useEffect(() => {\r\n // Update the key that to bind the FeeTable component to, so it re-initializes when the calculated fees table fees change\r\n setFeesTableKey(generateUuid());\r\n }, [feeTableFees]);\r\n\r\n useEffect(() => {\r\n const getProjectImageUrl = async () => {\r\n if (currentProjectImageUri.current !== projectInfo?.imageUri) {\r\n if (projectInfo?.imageUri) {\r\n // Fetch the latest project image if there is one\r\n try {\r\n const imageBlobUrl = await ProjectApi.getProjectImageBlobUrl(\r\n projectInfo?.id,\r\n projectInfo.imageUri,\r\n );\r\n\r\n setProjectImageBlobUrl(imageBlobUrl);\r\n } catch (error) {\r\n showErrorNotification(t('general:error'), t('project:projectImageLoadError'));\r\n }\r\n } else {\r\n // Clear the blob url because the project image may be removed or never set\r\n setProjectImageBlobUrl(null);\r\n }\r\n\r\n currentProjectImageUri.current = projectInfo?.imageUri;\r\n }\r\n };\r\n\r\n getProjectImageUrl();\r\n }, [projectImageBlobUrl, projectInfo?.id, projectInfo?.imageUri, showErrorNotification, t]);\r\n\r\n // Listen for Signal R project events.\r\n // NOTE: We put SignalR callback logic in observable subscription handlers because putting it directly in the useEffect\r\n // where we register things with SignalR over the network causes that code to clean up and run again when any of the dependencies change,\r\n // which can happen a LOT and cause data loss / unnecessary network activity.\r\n // When this code reruns because dependencies change, it only unsubscribes / re-subscribes to an observable, which is quick and\r\n // doesn't involve the network.\r\n // C'est la React. Viva RxJS.\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n signalRBroadcast_Project$.subscribe(\r\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\r\n // If we receive a message during the initial data load, hold on to the message to process after\r\n if (!isInitialDataLoadComplete) {\r\n notificationsReceivedDuringInitialDataLoad.current = [\r\n ...notificationsReceivedDuringInitialDataLoad.current,\r\n { type: 'project', notification: message },\r\n ];\r\n } else {\r\n await projectNotificationHandler(message);\r\n }\r\n },\r\n ),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [isInitialDataLoadComplete, projectNotificationHandler, signalRBroadcast_Project$]);\r\n\r\n // Listen for Signal R bid package events\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n // NOTE: We put SignalR callback logic in observables because putting them anywhere in the useEffect\r\n // where we register things causes the code to register / unregister when any of the dependencies change.\r\n allSubscriptions.add(\r\n signalRBroadcast_BidPackage$.subscribe(\r\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\r\n // If we receive a message during the initial data load, hold on to the message to process after\r\n if (!isInitialDataLoadComplete) {\r\n notificationsReceivedDuringInitialDataLoad.current = [\r\n ...notificationsReceivedDuringInitialDataLoad.current,\r\n { type: 'bid package', notification: message },\r\n ];\r\n } else {\r\n await bidPackageNotificationHandler(message);\r\n }\r\n },\r\n ),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [bidPackageNotificationHandler, isInitialDataLoadComplete, signalRBroadcast_BidPackage$]);\r\n\r\n // Listen for Signal R system settings events\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n signalRBroadcast_Settings$.subscribe(\r\n async (message: DataChangedNotificationMessage | EntityFrozenNotificationMessage) => {\r\n // If we receive a message during the initial data load, hold on to the message to process after\r\n if (!isInitialDataLoadComplete) {\r\n notificationsReceivedDuringInitialDataLoad.current = [\r\n ...notificationsReceivedDuringInitialDataLoad.current,\r\n { type: 'bid package', notification: message },\r\n ];\r\n } else {\r\n await systemSettingsNotificationHandler(message);\r\n }\r\n },\r\n ),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [isInitialDataLoadComplete, signalRBroadcast_Settings$, systemSettingsNotificationHandler]);\r\n\r\n // Register for project change notifications\r\n useEffect(() => {\r\n const registerForProjectChangeNotifications = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // NOTE: We have an ever-changing list of source ID's that we want to receive notifications\r\n // for (project, project notes, etc.).\r\n // We maintain a collection of the currently subscribed source ID's, so we can tell what changed\r\n // when this useEffect re-runs because of dependency change(s) and not do any unnecessary\r\n // un-registrations / re-registrations for source ID's that didn't change.\r\n const sourceIdsToUnregister = currentlyRegisteredProjectSourceIds.current.filter(\r\n (v) => !projectIdsForChangeNotifications.includes(v),\r\n );\r\n\r\n const sourceIdsToRegister = projectIdsForChangeNotifications.filter(\r\n (v) => !currentlyRegisteredProjectSourceIds.current.includes(v),\r\n );\r\n\r\n // Unregister from source ID's that we no longer need\r\n for (const currSourceId of sourceIdsToUnregister) {\r\n logger.logDebug(`unregistered notification group: ${currSourceId}`);\r\n\r\n NotificationService.unregisterFromNotifications(currSourceId);\r\n\r\n // Remove the current source ID from the running list of subscriptions\r\n currentlyRegisteredProjectSourceIds.current = currentlyRegisteredProjectSourceIds.current.filter(\r\n (v) => v !== currSourceId,\r\n );\r\n }\r\n\r\n // Register new source ID's\r\n // NOTE: the SourceId we be normalized to lowercase, when registering, so we'll need to account for that when checking it later.\r\n await NotificationService.batchRegisterForNotifications(sourceIdsToRegister, (message) =>\r\n onSignalRBroadcast_Project(message),\r\n );\r\n\r\n // Keep track of the registered sourceIds if all of them are registered successfully\r\n for (const currSourceId of sourceIdsToRegister) {\r\n logger.logDebug(`registered notification group: ${currSourceId}`);\r\n\r\n currentlyRegisteredProjectSourceIds.current.push(currSourceId);\r\n }\r\n } catch {\r\n setLiveUpdateRegistrationFailed(true);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n registerForProjectChangeNotifications();\r\n }, [\r\n hidePageLoadingOverlay,\r\n logger,\r\n onSignalRBroadcast_Project,\r\n projectIdsForChangeNotifications,\r\n showPageLoadingOverlay,\r\n ]);\r\n\r\n // Register for bid package change notifications\r\n useEffect(() => {\r\n const registerForBidPackageChangeNotifications = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // NOTE: We have an ever-changing list of source ID's that we want to receive notifications\r\n // for (bid package, bid package notes, bidder notes, adjustment notes, etc.).\r\n // We maintain a collection of the currently subscribed source ID's, so we can tell what changed\r\n // when this useEffect re-runs because of dependency change(s) and not do any unnecessary\r\n // un-registrations / re-registrations for source ID's that didn't change.\r\n const sourceIdsToUnregister = currentlyRegisteredBidPackageSourceIds.current.filter(\r\n (v) => !bidPackageIdsForChangeNotifications.includes(v),\r\n );\r\n\r\n const sourceIdsToRegister = bidPackageIdsForChangeNotifications.filter(\r\n (v) => !currentlyRegisteredBidPackageSourceIds.current.includes(v),\r\n );\r\n\r\n // Unregister from source ID's that we no longer need\r\n for (const currSourceId of sourceIdsToUnregister) {\r\n logger.logDebug(`unregistered notification group: ${currSourceId}`);\r\n\r\n NotificationService.unregisterFromNotifications(currSourceId);\r\n\r\n // Remove the current source ID from the running list of subscriptions\r\n currentlyRegisteredBidPackageSourceIds.current = currentlyRegisteredBidPackageSourceIds.current.filter(\r\n (v) => v !== currSourceId,\r\n );\r\n }\r\n\r\n // Register new source ID's\r\n // NOTE: the SourceId we be normalized to lowercase, when registering, so we'll need to account for that when checking it later.\r\n await NotificationService.batchRegisterForNotifications(sourceIdsToRegister, (message) =>\r\n onSignalRBroadcast_BidPackage(message),\r\n );\r\n\r\n // Keep track of the registered sourceIds if all of them are registered successfully\r\n for (const currSourceId of sourceIdsToRegister) {\r\n logger.logDebug(`registered notification group: ${currSourceId}`);\r\n\r\n currentlyRegisteredBidPackageSourceIds.current.push(currSourceId);\r\n }\r\n } catch {\r\n setLiveUpdateRegistrationFailed(true);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n registerForBidPackageChangeNotifications();\r\n }, [\r\n bidPackageIdsForChangeNotifications,\r\n hidePageLoadingOverlay,\r\n logger,\r\n onSignalRBroadcast_BidPackage,\r\n showPageLoadingOverlay,\r\n ]);\r\n\r\n // Register for settings change notifications\r\n useEffect(() => {\r\n const registerForSettingsChangeNotifications = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // NOTE: the SourceId we be normalized to lowercase, when registering, so we'll need to account for that when checking it later.\r\n await NotificationService.registerForNotifications(\r\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION,\r\n (message) => onSignalRBroadcast_Settings(message),\r\n );\r\n\r\n logger.logDebug(\r\n `registered notification group: ${GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION}`,\r\n );\r\n\r\n // NOTE: the SourceId we be normalized to lowercase, when registering, so we'll need to account for that when checking it later.\r\n await NotificationService.registerForNotifications(\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n (message) => onSignalRBroadcast_Settings(message),\r\n );\r\n\r\n logger.logDebug(\r\n `registered notification group: ${GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS}`,\r\n );\r\n } catch (error) {\r\n logger.logError(error);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n registerForSettingsChangeNotifications();\r\n }, [hidePageLoadingOverlay, logger, onSignalRBroadcast_Settings, showPageLoadingOverlay]);\r\n\r\n useEffect(() => {\r\n // When this component unmounts, unsubscribe from things\r\n return () => {\r\n [\r\n ...currentlyRegisteredBidPackageSourceIds.current,\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n ...currentlyRegisteredProjectSourceIds.current,\r\n GeneralConstants.ENTITY_IDS.BID_DAY_APPLICATION,\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n ].forEach((currSourceId) => {\r\n logger.logDebug(`unregistered notification group: ${currSourceId}`);\r\n\r\n NotificationService.unregisterFromNotifications(currSourceId);\r\n });\r\n };\r\n }, [logger]);\r\n\r\n // Listen for events\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n pageScroll_Y$.subscribe((offset) => {\r\n setPageIsScrolled_Y(offset >= 25);\r\n }),\r\n );\r\n\r\n // Bid amount change event\r\n allSubscriptions.add(\r\n bidAmountChange$.subscribe((bidValue: BidAmountValue) => {\r\n setBidPackages((currBidPackages) => {\r\n return onChangeCallback_BidAmount(currBidPackages, bidValue);\r\n });\r\n\r\n bidPackagesToUpdateFromSignalRHandler.current = onChangeCallback_BidAmount(\r\n bidPackagesToUpdateFromSignalRHandler.current,\r\n bidValue,\r\n );\r\n\r\n // NOTE: We do not include auto-save logic for this field\r\n }),\r\n );\r\n\r\n // Bid amount blur event\r\n allSubscriptions.add(\r\n bidAmountBlur$.subscribe(async (bidValue: BidAmountValue) => {\r\n const updateBidTotalsIsDirtyFlag = (bidPackagesToUpdate: BidPackage[]): BidPackage[] => {\r\n const copy = [...bidPackagesToUpdate];\r\n\r\n const matchingBidPackageIndex = copy.findIndex((v) => v.id === bidValue.bidPackageId);\r\n if (matchingBidPackageIndex > -1) {\r\n const matchingBidTotalIndex = copy[matchingBidPackageIndex].bidTotals.findIndex(\r\n (v) =>\r\n normalizeNullOrUndefined(v.alternateId) ===\r\n normalizeNullOrUndefined(bidValue.alternateId) &&\r\n normalizeNullOrUndefined(v.bidderId) ===\r\n normalizeNullOrUndefined(bidValue.bidderId),\r\n );\r\n\r\n if (matchingBidTotalIndex > -1) {\r\n const copy2 = [...copy[matchingBidPackageIndex].bidTotals];\r\n\r\n const newBidTotalObj = clone(copy2[matchingBidTotalIndex]);\r\n\r\n newBidTotalObj.isDirty = false;\r\n\r\n copy2[matchingBidTotalIndex] = newBidTotalObj;\r\n copy[matchingBidPackageIndex].bidTotals = copy2;\r\n }\r\n }\r\n\r\n return copy;\r\n };\r\n\r\n // Find the current bid total and reset the isDirty flag to false since we're \"committing\" the data in this function\r\n // by generating a command and sending it to the server\r\n setBidPackages((currBidPackages) => {\r\n if (!currBidPackages) {\r\n return currBidPackages;\r\n }\r\n\r\n return updateBidTotalsIsDirtyFlag(currBidPackages);\r\n });\r\n\r\n bidPackagesToUpdateFromSignalRHandler.current = updateBidTotalsIsDirtyFlag(\r\n bidPackagesToUpdateFromSignalRHandler.current,\r\n );\r\n\r\n const commandToProcess = onBlurCallback_BidAmount(\r\n bidPackages_Staging.current!,\r\n bidPackages,\r\n alternates,\r\n bidValue,\r\n );\r\n\r\n if (commandToProcess) {\r\n await executeCommand({\r\n commandToExecute: commandToProcess,\r\n commandBeforeExecutionCallback: () => {\r\n // Optimistically update the staging bid packages so other code has up to date values to use when generating commands\r\n bidPackages_Staging.current = successFunction_BidAmount(\r\n commandToProcess,\r\n alternates,\r\n bidPackages_Staging.current,\r\n bidPackages,\r\n );\r\n },\r\n commandSuccessCallback: () => {\r\n // If things succeeded, update the committed bid packages with the new data\r\n bidPackages_Committed.current = successFunction_BidAmount(\r\n commandToProcess,\r\n alternates,\r\n bidPackages_Committed.current,\r\n bidPackages,\r\n );\r\n },\r\n commandErrorCallback: () => {\r\n // If things failed, we restore the bid packages from the last committed data\r\n setBidPackages((bidPackages) => {\r\n return errorFunction_BidAmount(\r\n commandToProcess,\r\n alternates,\r\n bidPackages,\r\n bidPackages_Committed.current,\r\n );\r\n });\r\n\r\n bidPackages_Staging.current = errorFunction_BidAmount(\r\n commandToProcess,\r\n alternates,\r\n bidPackages_Staging.current,\r\n bidPackages_Committed.current!,\r\n );\r\n\r\n bidPackagesToUpdateFromSignalRHandler.current = errorFunction_BidAmount(\r\n commandToProcess,\r\n alternates,\r\n bidPackagesToUpdateFromSignalRHandler.current,\r\n bidPackages_Committed.current,\r\n );\r\n },\r\n commandTimeoutFunction: loadInitialData,\r\n });\r\n }\r\n }),\r\n );\r\n\r\n // Contingency change event\r\n allSubscriptions.add(\r\n contingencyChange$.subscribe((bidPackageContingencyAmount) => {\r\n setBidPackages((currBidPackages) => {\r\n return onChangeCallback_Contingency(currBidPackages, bidPackageContingencyAmount);\r\n });\r\n\r\n bidPackagesToUpdateFromSignalRHandler.current = onChangeCallback_Contingency(\r\n bidPackagesToUpdateFromSignalRHandler.current,\r\n bidPackageContingencyAmount,\r\n );\r\n\r\n // NOTE: We do not include auto-save logic for this field\r\n }),\r\n );\r\n\r\n // Contingency blur event\r\n allSubscriptions.add(\r\n contingencyBlur$.subscribe(async (bidPackageContingencyAmount) => {\r\n const commandToProcess = onBlurCallback_Contingency(\r\n bidPackages_Staging.current!,\r\n bidPackages,\r\n bidPackageContingencyAmount,\r\n );\r\n\r\n if (commandToProcess) {\r\n await executeCommand({\r\n commandToExecute: commandToProcess,\r\n commandBeforeExecutionCallback: () => {\r\n // Optimistically update the staging bid packages so other code has up to date values to use when generating commands\r\n bidPackages_Staging.current = successFunction_Contingency(\r\n commandToProcess,\r\n bidPackages_Staging.current,\r\n bidPackages,\r\n );\r\n },\r\n commandSuccessCallback: () => {\r\n // If things succeeded, update the committed bid packages with the new data\r\n bidPackages_Committed.current = successFunction_Contingency(\r\n commandToProcess,\r\n bidPackages_Committed.current,\r\n bidPackages,\r\n );\r\n },\r\n commandErrorCallback: () => {\r\n // If things failed, we restore the bid packages from the last committed data\r\n setBidPackages((bidPackages) => {\r\n return errorFunction_Contingency(\r\n commandToProcess,\r\n bidPackages,\r\n bidPackages_Committed.current,\r\n );\r\n });\r\n\r\n bidPackages_Staging.current = errorFunction_Contingency(\r\n commandToProcess,\r\n bidPackages_Staging.current,\r\n bidPackages_Committed.current!,\r\n );\r\n\r\n bidPackagesToUpdateFromSignalRHandler.current = errorFunction_Contingency(\r\n commandToProcess,\r\n bidPackagesToUpdateFromSignalRHandler.current,\r\n bidPackages_Committed.current!,\r\n );\r\n },\r\n commandTimeoutFunction: loadInitialData,\r\n });\r\n }\r\n }),\r\n );\r\n\r\n // Alternate enabled change event\r\n allSubscriptions.add(\r\n alternateChange$.subscribe(\r\n async (value: UpdateAlternateEnabledStatusValue): Promise => {\r\n // We do not rely on a blur event before committing changes, we just update state and then create the command\r\n // to send to the server\r\n setAlternates((alternates) => {\r\n return alternates\r\n ? onChangeCallback_Alternate(alternates, value.alternateName!, value.value)\r\n : alternates;\r\n });\r\n\r\n alternatesToUpdateFromSignalRHandler.current = onChangeCallback_Alternate(\r\n alternatesToUpdateFromSignalRHandler.current,\r\n value.alternateName!,\r\n value.value,\r\n );\r\n\r\n const commandToProcess = createAlternateUpdateCommand(\r\n projectInfo!.id,\r\n value.alternateName!,\r\n value.value,\r\n );\r\n\r\n if (commandToProcess) {\r\n await executeCommand({\r\n commandToExecute: commandToProcess,\r\n commandBeforeExecutionCallback: () => {\r\n // Optimistically update the staging alternates so other code has up to date values to use when generating commands\r\n alternates_Staging.current = !alternates_Staging.current\r\n ? alternates_Staging.current\r\n : successFunction_Alternate(\r\n commandToProcess,\r\n alternates_Staging.current,\r\n alternates,\r\n );\r\n },\r\n commandSuccessCallback: () => {\r\n // If things succeeded, update the committed alternates with the new data\r\n alternates_Committed.current = !alternates_Committed.current\r\n ? alternates_Committed.current\r\n : successFunction_Alternate(\r\n commandToProcess,\r\n alternates_Committed.current,\r\n alternates,\r\n );\r\n },\r\n commandErrorCallback: () => {\r\n // If things failed, we restore the staging alternates from the last committed data\r\n alternates_Staging.current = !alternates_Staging.current\r\n ? alternates_Staging.current\r\n : errorFunction_Alternate(\r\n commandToProcess,\r\n alternates_Staging.current,\r\n alternates_Committed.current,\r\n );\r\n\r\n // If things failed, we restore the current alternates from the last committed data\r\n setAlternates((alternates) => {\r\n return !alternates\r\n ? alternates\r\n : errorFunction_Alternate(\r\n commandToProcess,\r\n alternates,\r\n alternates_Committed.current,\r\n );\r\n });\r\n\r\n alternatesToUpdateFromSignalRHandler.current = errorFunction_Alternate(\r\n commandToProcess,\r\n alternatesToUpdateFromSignalRHandler.current,\r\n alternates_Committed.current,\r\n );\r\n },\r\n });\r\n }\r\n },\r\n ),\r\n );\r\n\r\n // Edit project bidders ranges\r\n allSubscriptions.add(\r\n projectEditBiddersRanges$.subscribe(\r\n async (value: ProjectBiddersRanges): Promise => {\r\n //let make sure that we have the project's preferences so that we can display the modal ui for editing the number of bidders ranges\r\n if (projectInfo && value) {\r\n setCurrentProjectBiddersRangesModalState({\r\n isOpen: true,\r\n projectId: projectInfo.id,\r\n projectBiddersRangesToEdit: clone(value),\r\n isReadOnly: isReadOnly,\r\n });\r\n }\r\n },\r\n ),\r\n );\r\n\r\n // Bid summary display options changed\r\n allSubscriptions.add(\r\n bidSummaryDisplayOptionsChange$.subscribe((newBidSummaryOptions: BidSummaryOptions): void => {\r\n const originalDisplayAssignedToValue = bidSummaryOptions.displayAssignedToColumn;\r\n\r\n setBidSummaryOptions(newBidSummaryOptions);\r\n\r\n // Refresh the grid\r\n setGridRerenderTriggerObject({\r\n rowsChanged: true,\r\n primaryGridColumnsChanged:\r\n originalDisplayAssignedToValue !== newBidSummaryOptions.displayAssignedToColumn,\r\n });\r\n }),\r\n );\r\n\r\n // Edit project notes\r\n allSubscriptions.add(\r\n projectEditNotes$.subscribe((): void => {\r\n setNotesModalIsOpen(true);\r\n }),\r\n );\r\n\r\n // Show project info\r\n allSubscriptions.add(\r\n projectShowInfo$.subscribe((project: DetailProjectInfo): void => {\r\n showProjectInfo(project);\r\n }),\r\n );\r\n\r\n // Close project\r\n allSubscriptions.add(\r\n projectClose$.subscribe((): void => {\r\n showConfirmationOverlay({\r\n text: t('bid-summary:confirmCloseProject'),\r\n buttons: [\r\n {\r\n text: t('general:yes'),\r\n onClick: async (): Promise => {\r\n hideConfirmationOverlay();\r\n\r\n await executeCommand({\r\n commandToExecute: new CloseProjectCommand(projectInfo!.id),\r\n commandExecutionType: 'relies-on-signal-r-for-completion',\r\n commandSuccessCallback: () => {\r\n setProjectInfo({ ...projectInfo!, isClosed: true });\r\n detailProjectInfoToUpdateFromSignalRHandler.current = { ...projectInfo! };\r\n\r\n showSuccessNotification(\r\n t('general:success'),\r\n t('bid-summary:closeProjectSuccess'),\r\n );\r\n },\r\n commandErrorCallback: () => {\r\n showErrorNotification(t('general:error'), t('bid-summary:closeProjectError'));\r\n },\r\n });\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:no'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n }),\r\n );\r\n\r\n allSubscriptions.add(\r\n projectExportExcel$.subscribe(() => {\r\n downloadProjectExport();\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [\r\n alternateChange$,\r\n alternates,\r\n bidAmountBlur$,\r\n bidAmountChange$,\r\n bidPackages,\r\n bidSummaryDisplayOptionsChange$,\r\n bidSummaryOptions.displayAssignedToColumn,\r\n contingencyBlur$,\r\n contingencyChange$,\r\n createAlternateUpdateCommand,\r\n downloadProjectExport,\r\n errorFunction_Alternate,\r\n errorFunction_BidAmount,\r\n errorFunction_Contingency,\r\n executeCommand,\r\n hideConfirmationOverlay,\r\n isReadOnly,\r\n loadInitialData,\r\n onBlurCallback_BidAmount,\r\n onBlurCallback_Contingency,\r\n onChangeCallback_Alternate,\r\n onChangeCallback_BidAmount,\r\n onChangeCallback_Contingency,\r\n pageScroll_Y$,\r\n projectClose$,\r\n projectEditBiddersRanges$,\r\n projectEditNotes$,\r\n projectExportExcel$,\r\n projectInfo,\r\n projectShowInfo$,\r\n setCurrentProjectBiddersRangesModalState,\r\n showConfirmationOverlay,\r\n showErrorNotification,\r\n showProjectInfo,\r\n showSuccessNotification,\r\n successFunction_Alternate,\r\n successFunction_BidAmount,\r\n successFunction_Contingency,\r\n t,\r\n ]);\r\n\r\n // Listen for fees events\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n // Fee amount change event\r\n allSubscriptions.add(\r\n feeAmountChange$.subscribe((feeAndAmount: FeeNameAndAmount) => {\r\n const updateFeeAmount = (feesToUpdate: Fee[]): Fee[] => {\r\n const copy = [...feesToUpdate];\r\n\r\n const feeToUpdate = copy.find((f) => f.name === feeAndAmount.feeName);\r\n if (!feeToUpdate) {\r\n return feesToUpdate;\r\n }\r\n\r\n feeToUpdate.amount = feeAndAmount.amount;\r\n\r\n return copy;\r\n };\r\n\r\n setProjectFees((fees) => updateFeeAmount(fees));\r\n\r\n feesToUpdateFromSignalRHandler.current = updateFeeAmount(\r\n feesToUpdateFromSignalRHandler.current,\r\n );\r\n }),\r\n );\r\n\r\n // Fee amount blur event\r\n allSubscriptions.add(\r\n feeAmountBlur$.subscribe(async (feeAndAmount: FeeNameAndAmount) => {\r\n if (!projectInfo) {\r\n return;\r\n }\r\n\r\n const originalFeeAmount = projectFees_Committed.current.find(\r\n (v) => v.name === feeAndAmount.feeName,\r\n );\r\n\r\n // If things didn't change, don't do anything\r\n if (!originalFeeAmount || originalFeeAmount.amount === feeAndAmount.amount) {\r\n return;\r\n }\r\n\r\n const batchCommand = new ProjectFeesBatchCommand();\r\n batchCommand.addCommand(\r\n new UpdateProjectFeeCommand(\r\n projectInfo.id,\r\n feeAndAmount.feeName,\r\n undefined,\r\n undefined,\r\n feeAndAmount.amount,\r\n ),\r\n );\r\n\r\n await executeCommand({\r\n commandToExecute: batchCommand,\r\n commandExecutionType: 'relies-on-signal-r-for-completion',\r\n commandSuccessCallback: () => {\r\n const updateFees = (feesToUpdate: Fee[]): Fee[] => {\r\n const newArray = [...feesToUpdate];\r\n\r\n const matchingFeeIndex = newArray.findIndex((v) => v.name === feeAndAmount.feeName);\r\n if (matchingFeeIndex === -1) {\r\n return newArray;\r\n }\r\n\r\n const newObj = clone(newArray[matchingFeeIndex]);\r\n newObj.amount = feeAndAmount.amount;\r\n\r\n newArray[matchingFeeIndex] = newObj;\r\n\r\n return newArray;\r\n };\r\n\r\n projectFees_Committed.current = updateFees(projectFees_Committed.current);\r\n\r\n feesToUpdateFromSignalRHandler.current = updateFees(\r\n feesToUpdateFromSignalRHandler.current,\r\n );\r\n },\r\n });\r\n }),\r\n );\r\n\r\n // Fee calculation request blur event\r\n allSubscriptions.add(\r\n feeCalculationRequest$.subscribe(async () => {\r\n await FeeApi.calculateFeesForProject(routeParams.projectId);\r\n showInfoNotification(t('general:info'), t('bid-summary:feeCalculationRequested'));\r\n }),\r\n );\r\n\r\n // Fees edit event\r\n allSubscriptions.add(\r\n feesEdit$.subscribe(() => {\r\n setFeesModalIsOpen(true);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [\r\n executeCommand,\r\n feeAmountBlur$,\r\n feeAmountChange$,\r\n feeCalculationRequest$,\r\n feesEdit$,\r\n projectInfo,\r\n routeParams.projectId,\r\n showInfoNotification,\r\n t,\r\n ]);\r\n\r\n // Listen for fees events\r\n useEffect(() => {\r\n // NOTE: We can use a subscription object to hold many subscriptions and unsubscribe from everything at once\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n keyboardShortcutsShow$.subscribe(() => {\r\n setKeyboardShortcutsInfoIsOpen(true);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [keyboardShortcutsShow$]);\r\n\r\n // Add to recent projects\r\n useEffect(() => {\r\n // We aren't awaiting this because we don't care about the result\r\n RecentProjectsApi.addRecentProject(routeParams.projectId);\r\n }, [routeParams.projectId]);\r\n\r\n // Set header\r\n useEffect(() => {\r\n if (projectInfo) {\r\n setBidSummaryPageHeader(\r\n generateBidSummaryPageHeader({\r\n liveUpdateRegistrationFailed,\r\n isReadOnly,\r\n projectInfo,\r\n projectImageBlobUrl,\r\n bidSummaryOptions,\r\n projectHasNotes: !!projectInfo?.notes,\r\n pageIsScrolled: pageIsScrolled_Y,\r\n anyEntitiesAreFrozen:\r\n projectIsFrozen ||\r\n projectNotesAreFrozen ||\r\n bidPackageIdsThatAreFrozen.length > 0 ||\r\n adjustmentNoteIdsThatAreFrozen.length > 0,\r\n projectSettingsAreFrozen: bidDayApplicationEntityIsFrozen || systemSettingsEntityIsFrozen,\r\n }),\r\n );\r\n }\r\n }, [\r\n isReadOnly,\r\n projectInfo,\r\n bidSummaryOptions,\r\n generateBidSummaryPageHeader,\r\n pageIsScrolled_Y,\r\n projectIsFrozen,\r\n projectNotesAreFrozen,\r\n bidPackageIdsThatAreFrozen.length,\r\n adjustmentNoteIdsThatAreFrozen,\r\n liveUpdateRegistrationFailed,\r\n bidDayApplicationEntityIsFrozen,\r\n systemSettingsEntityIsFrozen,\r\n projectImageBlobUrl,\r\n ]);\r\n\r\n // Set grid sections\r\n useEffect(() => {\r\n // Don't set the grid sections until the initial data is loaded, because otherwise we can render header rows\r\n // with no content, and then suddenly, BAM, content!\r\n if (!isInitialDataLoadComplete) {\r\n return;\r\n }\r\n\r\n const summaryGridSections = generateSummaryGridSections();\r\n setGridSections(summaryGridSections);\r\n }, [generateSummaryGridSections, isInitialDataLoadComplete]);\r\n\r\n const getFrozenEntitiesNames = (): string[] => {\r\n let returnValue: string[] = [];\r\n\r\n if (bidDayApplicationEntityIsFrozen) {\r\n returnValue.push(t('general:applicationSettings'));\r\n }\r\n\r\n if (systemSettingsEntityIsFrozen) {\r\n returnValue.push(t('general:systemSettings'));\r\n }\r\n\r\n if (projectIsFrozen) {\r\n returnValue.push(`${t('general:this')} ${t('general:project')}`);\r\n }\r\n\r\n if (projectNotesAreFrozen) {\r\n returnValue.push(t('bid-summary:projectNotes'));\r\n }\r\n\r\n // If we have bid packages that are frozen, show the user the bid package name\r\n if (bidPackageIdsThatAreFrozen.length > 0) {\r\n bidPackageIdsThatAreFrozen.forEach((v) => {\r\n const matchingBidPackage = bidPackages.find((m) => m.id === v);\r\n\r\n if (matchingBidPackage) {\r\n returnValue.push(\r\n `${t('general:bidPackage')} - ${matchingBidPackage.code} - ${\r\n matchingBidPackage.description\r\n }`,\r\n );\r\n }\r\n });\r\n }\r\n\r\n // If we have adjustment notes that are frozen, show the user the bid package name / alternate name\r\n if (adjustmentNoteIdsThatAreFrozen.length > 0) {\r\n adjustmentNoteIdsThatAreFrozen.forEach((currFrozenNotesId) => {\r\n const matchingBidPackage = bidPackages.find((m) =>\r\n m.adjustments.some((k) => k.notesId === currFrozenNotesId),\r\n );\r\n\r\n if (matchingBidPackage) {\r\n const matchingAdjustment = matchingBidPackage.adjustments.find(\r\n (m) => m.notesId === currFrozenNotesId,\r\n )!;\r\n\r\n let matchingAlternateName = matchingAdjustment.alternateId\r\n ? alternates.find((m) => m.id === matchingAdjustment.alternateId)?.name\r\n : '';\r\n\r\n matchingAlternateName = matchingAlternateName ? ` (${matchingAlternateName})` : '';\r\n\r\n returnValue.push(`\r\n ${t('bid-package:adjustmentNotes')} - ${matchingBidPackage.code} - ${\r\n matchingBidPackage.description\r\n }${matchingAlternateName}`);\r\n }\r\n });\r\n }\r\n\r\n returnValue = sortBy(returnValue, (v) => v);\r\n\r\n return returnValue;\r\n };\r\n\r\n const frozenEntitiesNameStrings = getFrozenEntitiesNames();\r\n\r\n return (\r\n
    \r\n {projectInfo ? (\r\n <>\r\n {bidSummaryPageHeader}\r\n\r\n {gridSections.length ? (\r\n <>\r\n {frozenEntitiesNameStrings.length > 0 ? (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n 0 ? 'noTopMargin' : ''\r\n }`}\r\n >\r\n \r\n
    \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n \r\n \r\n \r\n\r\n setFeesModalIsOpen(false)}\r\n provideFocusTrapCode={true}\r\n addExtraSpaceAtBottom\r\n >\r\n {\r\n const success = await onSaveClick();\r\n if (success) {\r\n setFeesModalIsOpen(false);\r\n }\r\n }}\r\n discardCallback={() => {\r\n setFeesModalIsOpen(false);\r\n discardCallback();\r\n }}\r\n bidTotal={Project.calculateProjectBidTotal(bidPackages, alternates)}\r\n />\r\n \r\n\r\n
    {getProjectBiddersRangesModalJSX()}
    \r\n\r\n {getProjectInfoJSX()}\r\n\r\n {\r\n setKeyboardShortcutsInfoIsOpen(false);\r\n }}\r\n provideFocusTrapCode\r\n addExtraSpaceAtBottom\r\n >\r\n \r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n \r\n );\r\n};\r\n\r\n// Data change types that can affect the layout / rows of the grid containing the bid packages / fees grid sections\r\nconst dataChangeEntryTypesThatCanAffectGrid: DataChangedEntryTypes_BidSummaryPage[] = [\r\n 'Bidder',\r\n 'Alternate',\r\n 'BidPackage',\r\n 'Fee',\r\n];\r\n\r\nconst BidSummaryPage: React.FC = () => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default BidSummaryPage;\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class CreateProjectCommand extends CommandBase {\r\n constructor(\r\n public information: ProjectInformationDTO,\r\n public bidPackagesToInclude: string[],\r\n public bidPackageAssignments: ProjectBidPackageAssignmentDTO[],\r\n public generalRequirementsToInclude: string[],\r\n public alternates: string[],\r\n public feesToInclude: string[],\r\n public permissions: ProjectPermissionsDTO,\r\n ) {\r\n super('DESTINI.BidDay.Commands.CreateProject', 'project/create-project', 'post');\r\n }\r\n}\r\n","import { CommandBase } from '../CommandBase';\r\n\r\nexport class UpdateProjectCommand extends CommandBase {\r\n constructor(\r\n public id: string,\r\n public information: ProjectInformationDTO,\r\n public bidPackagesToInclude: string[],\r\n public bidPackagesToExclude: string[],\r\n public bidPackageAssignments: ProjectBidPackageAssignmentDTO[],\r\n public generalRequirementsToInclude: string[],\r\n public generalRequirementsToExclude: string[],\r\n public alternatesToUpdate: ProjectAlternateUpdateDTO[],\r\n public alternatesToAdd: string[],\r\n public alternatesToDelete: string[],\r\n public feesToInclude: string[],\r\n public feesToExclude: string[],\r\n public permissions: ProjectPermissionsDTO,\r\n ) {\r\n super('DESTINI.BidDay.Commands.UpdateProject', 'project/update-project', 'post');\r\n }\r\n}\r\n//TODO: Consider max/min edge cases for exclude/includes\r\n","import ApplicationRoutes from './../constants/routes/index';\r\n\r\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\r\nconst navigateBack = (history: any): void => {\r\n if (history.length > 2) {\r\n // If the user has a valid navigation history, navigate to the previous page\r\n history.goBack();\r\n } else {\r\n // Else navigate back home\r\n history.push(ApplicationRoutes.HOME);\r\n }\r\n};\r\n\r\nexport { navigateBack };\r\n","import { uniq } from 'lodash';\nimport React from 'react';\nimport './ProjectErrorDisplay.scss';\n\ninterface Props {\n errorId: string;\n errors: ProjectError[];\n}\n\nconst ProjectErrorDisplay: React.FC = ({ errorId, errors }) => {\n const errorsToDisplay = getErrorMessagesById(errors, errorId);\n\n return (\n
    \n
    \n {errorsToDisplay.length === 0 ? (\n <>\n ) : (\n uniq(errorsToDisplay).map((errorMessage) => {\n return (\n \n );\n })\n )}\n
    \n
    \n );\n};\n\nconst getErrorMessagesById = (errors: ProjectError[], id: string): string[] => {\n return errors.filter((error) => error.id === id).map((error) => error.message);\n};\n\nexport default ProjectErrorDisplay;\n","import { Input } from '@progress/kendo-react-inputs';\r\nimport React, { MutableRefObject, useContext, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport GeneralConstants from '../../../../../constants/general';\r\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\r\nimport { generateUuid } from '../../../../../utils/uuid';\r\nimport { ConfirmationOverlayContext } from '../../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport BTIconButton from '../../../../common-page-components/controls/icon-button/BTIconButton';\r\nimport BTInput from '../../../../common-page-components/inputs/BTInput';\r\nimport ProjectErrorDisplay from './ProjectErrorDisplay';\r\n\r\ninterface Props {\r\n alternates: ProjectAlternate[];\r\n errorId: string;\r\n errors: ProjectError[];\r\n updateAlternates: (alternates: ProjectAlternate[]) => void;\r\n}\r\n\r\n// This component handles display of the alternates section and related errors when adding or editing a project\r\nconst AddEditAlternates: React.FC = ({ alternates, errorId, errors, updateAlternates }) => {\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n\r\n const { t } = useTranslation();\r\n const [newAlternate, setNewAlternate] = useState('');\r\n\r\n const alternateInputRef: MutableRefObject = useRef(null);\r\n\r\n const onAddClick = (): void => {\r\n const updatedAlternates = [\r\n ...alternates,\r\n { id: generateUuid(), name: newAlternate.trim() } as ProjectAlternate,\r\n ];\r\n updateAlternates(updatedAlternates);\r\n setNewAlternate('');\r\n alternateInputRef.current!.focus();\r\n };\r\n\r\n const onDeleteClick = (alternate: ProjectAlternate): void => {\r\n const deleteAlternate = () => {\r\n const updatedAlternates = alternates.filter((a) => a !== alternate);\r\n updateAlternates(updatedAlternates);\r\n };\r\n\r\n if (alternate.hasLineItems) {\r\n // If the alternate has line items, confirm deletion\r\n showConfirmationOverlay({\r\n text: t('project:confirmAlternateDelete', { alternate: alternate.name }),\r\n buttons: [\r\n {\r\n text: t('general:yes'),\r\n onClick: (): void => {\r\n deleteAlternate();\r\n hideConfirmationOverlay();\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:no'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n } else {\r\n // Otherwise just delete it\r\n deleteAlternate();\r\n }\r\n };\r\n\r\n return (\r\n
    \r\n {alternates.map((a) => {\r\n return (\r\n
    \r\n
    \r\n {\r\n const index = alternates.indexOf(a);\r\n const updatedAlternates = [...alternates];\r\n updatedAlternates[index] = {\r\n ...updatedAlternates[index],\r\n name: event.target.value as string,\r\n };\r\n updateAlternates(updatedAlternates);\r\n }}\r\n />\r\n
    \r\n
    \r\n onDeleteClick(a)}\r\n data-testid={'delete-alternate-data-testid'}\r\n />\r\n
    \r\n
    \r\n );\r\n })}\r\n\r\n
    \r\n
    \r\n {\r\n setNewAlternate(event.value);\r\n }}\r\n ref={alternateInputRef}\r\n onKeyDown={(e) => {\r\n if (e.key === GeneralConstants.KEY_ENTER && (newAlternate || '').trim().length) {\r\n onAddClick();\r\n }\r\n }}\r\n maxLength={EntityValidationConstants.AlternateEntityLimits.Name_MaxLength}\r\n />\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n \r\n
    \r\n );\r\n};\r\n\r\nexport default AddEditAlternates;\r\n","import React, { useState } from 'react';\r\nimport { generateUuid } from '../../../utils/uuid';\r\nimport './BTCheckBox.scss';\r\n\r\ntype Orientation = 'horizontal' | 'vertical';\r\n\r\ninterface Props {\r\n id: string;\r\n name?: string;\r\n label: string;\r\n className: string;\r\n checked: boolean;\r\n disabled?: boolean;\r\n orientation: Orientation;\r\n onChange: (event: React.ChangeEvent) => void;\r\n}\r\n\r\nconst BTCheckBox: React.FC = (props) => {\r\n const [inputIdentifier] = useState(\r\n props.id || props.name || props.label || generateUuid(),\r\n );\r\n\r\n const containerClassNames = ['d-inline-flex', 'w-100'];\r\n\r\n props.orientation === 'vertical'\r\n ? containerClassNames.push('flex-column-reverse')\r\n : containerClassNames.push('flex-row align-items-center');\r\n\r\n return (\r\n
    \r\n {\r\n if (inputIdentifier && e && !e.getAttribute('data-testid')) {\r\n e.setAttribute('data-testid', inputIdentifier);\r\n }\r\n }}\r\n />\r\n \r\n
    \r\n );\r\n};\r\n\r\nexport default BTCheckBox;\r\n","import { DropDownListBlurEvent } from '@progress/kendo-react-dropdowns';\r\nimport lodash, { clone } from 'lodash';\r\nimport React, { useMemo } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { UserRolesValues } from '../../../../../constants/users/user-roles';\r\nimport { getEmailWithoutDomain } from '../../../../../utils/strings';\r\nimport BTCheckBox from '../../../../common-page-components/inputs/BTCheckBox';\r\nimport BTDropDownList, {\r\n BTDropDownListOption,\r\n} from '../../../../common-page-components/inputs/BTDropDownList';\r\nimport ProjectErrorDisplay from './ProjectErrorDisplay';\r\n\r\ninterface Props {\r\n bidPackages: ProjectBidPackage[];\r\n frozenBidPackageIds: string[];\r\n users: User[];\r\n errorId: string;\r\n errors: ProjectError[];\r\n updateBidPackages: (bidPackages: ProjectBidPackage[], shouldUpdateContributors: boolean) => void;\r\n}\r\n\r\n// This component handles display of the bid packages section and related errors when adding or editing a project\r\nconst AddEditBidPackages: React.FC = ({\r\n bidPackages,\r\n frozenBidPackageIds,\r\n users,\r\n errorId,\r\n errors,\r\n updateBidPackages,\r\n}) => {\r\n const { t } = useTranslation();\r\n\r\n // Filter out the roles down to Contributors and map into BTDropDownList options\r\n const userOptions: BTDropDownListOption[] = useMemo(() => {\r\n const options: BTDropDownListOption[] = lodash(users)\r\n .filter((u) => u.roles.find((v) => v.id === UserRolesValues.Contributor) !== undefined)\r\n .groupBy((u) => u.name?.toLowerCase()) // Group by name to find duplicates\r\n .flatMap((users) => {\r\n const isDupe = users.length > 1;\r\n\r\n return users.map((u) => {\r\n let name;\r\n if (u.name) {\r\n // For users with duplicate names, display their email as well (without the domain)\r\n name = !isDupe ? u.name : `${u.name} (${getEmailWithoutDomain(u.email)})`;\r\n } else {\r\n name = getEmailWithoutDomain(u.email);\r\n }\r\n\r\n return {\r\n name: name,\r\n value: u.email,\r\n };\r\n });\r\n })\r\n .orderBy((u) => u.name)\r\n .value();\r\n\r\n // Add a default option to the top of the collection\r\n options.unshift({\r\n name: t('general:none'),\r\n value: null,\r\n });\r\n\r\n return options;\r\n }, [t, users]);\r\n\r\n return (\r\n
    \r\n
    \r\n {!bidPackages.length ? (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n\r\n {bidPackages.length ? (\r\n <>\r\n
    \r\n
    \r\n
    \r\n {\r\n updateBidPackages(\r\n bidPackages.map((v) => {\r\n // If the bid package is frozen, do not adjust its selection\r\n if (frozenBidPackageIds.includes(v.id)) {\r\n return v;\r\n }\r\n\r\n const newBidPackage = clone(v);\r\n newBidPackage.isSelected = true;\r\n return newBidPackage;\r\n }),\r\n false,\r\n );\r\n }}\r\n >\r\n {t('general:selectAll')}\r\n
    \r\n {\r\n updateBidPackages(\r\n bidPackages.map((v) => {\r\n // If the bid package is frozen, do not adjust its selection\r\n if (frozenBidPackageIds.includes(v.id)) {\r\n return v;\r\n }\r\n\r\n const newBidPackage = clone(v);\r\n newBidPackage.isSelected = false;\r\n return newBidPackage;\r\n }),\r\n false,\r\n );\r\n }}\r\n >\r\n {t('general:deselectAll')}\r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n\r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {bidPackages.map((bp) => {\r\n return (\r\n
    \r\n
    \r\n
    \r\n
    \r\n {\r\n // Select the bid package being edited\r\n const targetBidPackage = clone(bp);\r\n // Update the property with the correct value and sync changes with parent\r\n targetBidPackage.isSelected = event.target.checked;\r\n updateBidPackages(\r\n bidPackages.map((bidPackage) =>\r\n bidPackage === bp ? targetBidPackage : bidPackage,\r\n ),\r\n false,\r\n );\r\n }}\r\n />\r\n
    \r\n
    \r\n
    \r\n {\r\n // Select the bid package being edited\r\n const targetBidPackage = clone(bp);\r\n\r\n // Update the property with the correct value and sync changes with parent\r\n targetBidPackage.assignedToUser = value as string;\r\n\r\n updateBidPackages(\r\n bidPackages.map((bidPackage) =>\r\n bidPackage === bp ? targetBidPackage : bidPackage,\r\n ),\r\n false,\r\n );\r\n }}\r\n onBlurHandler={(event: DropDownListBlurEvent) => {\r\n // Select the bid package being edited\r\n const targetBidPackage = clone(bp);\r\n\r\n targetBidPackage.assignedToUser = event.target.value.value as string; // Yo dawg, I heard you need a value\r\n\r\n updateBidPackages(\r\n bidPackages.map((bidPackage) =>\r\n bidPackage === bp ? targetBidPackage : bidPackage,\r\n ),\r\n true,\r\n );\r\n }}\r\n />\r\n
    \r\n
    \r\n
    \r\n );\r\n })}\r\n \r\n \r\n );\r\n};\r\n\r\nexport default AddEditBidPackages;\r\n","import { clone } from 'lodash';\r\nimport React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { formatNumberAsCurrency, formatNumberAsPercentage } from '../../../../../utils/general';\r\nimport BTCheckBox from '../../../../common-page-components/inputs/BTCheckBox';\r\nimport { FeeTypes } from '../../../../enums/fee-enum';\r\nimport ProjectErrorDisplay from './ProjectErrorDisplay';\r\n\r\ninterface Props {\r\n fees: ProjectFee[];\r\n errorId: string;\r\n errors: ProjectError[];\r\n updateFees: (fees: ProjectFee[]) => void;\r\n}\r\n\r\n// This component handles display of the fees section when adding or editing\r\nconst AddEditFees: React.FC = ({ fees, errorId, errors, updateFees }) => {\r\n const { t } = useTranslation();\r\n\r\n const renderFeeValue = (fee: ProjectFee) => {\r\n switch (fee.feeType) {\r\n case FeeTypes.Subtotal:\r\n return <>;\r\n case FeeTypes.LumpSum:\r\n return ;\r\n default:\r\n return ;\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n
    \r\n {\r\n const copy = [...fees];\r\n copy.forEach((m) => (m.isSelected = true));\r\n updateFees(copy);\r\n }}\r\n >\r\n {t('general:selectAll')}\r\n
    \r\n {\r\n const copy = [...fees];\r\n copy.forEach((m) => (m.isSelected = false));\r\n updateFees(copy);\r\n }}\r\n >\r\n {t('general:deselectAll')}\r\n \r\n \r\n\r\n
    \r\n\r\n
    \r\n
    \r\n {fees.length ? (\r\n <>\r\n
    \r\n \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n\r\n {fees.map((fee) => {\r\n return (\r\n
    \r\n
    \r\n
    \r\n {\r\n // Select the fee being edited\r\n const targetFee = clone(fee);\r\n // Update the property with the correct value and sync changes with parent\r\n targetFee.isSelected = event.target.checked;\r\n updateFees(\r\n fees.map((f) => {\r\n return f === fee ? targetFee : f;\r\n }),\r\n );\r\n }}\r\n />\r\n
    \r\n
    {renderFeeValue(fee)}
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n );\r\n })}\r\n \r\n
    \r\n \r\n );\r\n};\r\n\r\nexport default AddEditFees;\r\n","import { clone } from 'lodash';\r\nimport React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport BTCheckBox from '../../../../common-page-components/inputs/BTCheckBox';\r\n\r\ninterface Props {\r\n generalRequirements: ProjectGeneralRequirement[];\r\n updateGeneralRequirements: (generalRequirements: ProjectGeneralRequirement[]) => void;\r\n}\r\n\r\n// This component handles display of the general requirements section when adding or editing a project\r\nconst AddEditGeneralRequirements: React.FC = ({\r\n generalRequirements,\r\n updateGeneralRequirements,\r\n}) => {\r\n const { t } = useTranslation();\r\n\r\n return (\r\n <>\r\n {generalRequirements.length ? (\r\n <>\r\n
    \r\n {\r\n updateGeneralRequirements(\r\n generalRequirements.map((v) => {\r\n const newGeneralRequirement = clone(v);\r\n newGeneralRequirement.isSelected = true;\r\n return newGeneralRequirement;\r\n }),\r\n );\r\n }}\r\n >\r\n {t('general:selectAll')}\r\n
    \r\n {\r\n updateGeneralRequirements(\r\n generalRequirements.map((v) => {\r\n const newGeneralRequirement = clone(v);\r\n newGeneralRequirement.isSelected = false;\r\n return newGeneralRequirement;\r\n }),\r\n );\r\n }}\r\n >\r\n {t('general:deselectAll')}\r\n \r\n \r\n\r\n
    \r\n\r\n {generalRequirements.map((gr) => {\r\n return (\r\n
    \r\n {\r\n // Select the general requirement being edited\r\n const targetRequirement = clone(gr);\r\n // Update the property with the correct value and sync changes with parent\r\n targetRequirement.isSelected = event.target.checked;\r\n updateGeneralRequirements(\r\n generalRequirements.map((requirement) =>\r\n requirement === gr ? targetRequirement : requirement,\r\n ),\r\n );\r\n }}\r\n />\r\n
    \r\n );\r\n })}\r\n \r\n ) : (\r\n <>\r\n )}\r\n \r\n );\r\n};\r\n\r\nexport default AddEditGeneralRequirements;\r\n","import { CompositeFilterDescriptor, filterBy, FilterDescriptor } from '@progress/kendo-data-query';\r\nimport { MultiSelect, MultiSelectProps } from '@progress/kendo-react-dropdowns';\r\nimport { sortBy } from 'lodash';\r\nimport React, { useState } from 'react';\r\nimport { generateUuid } from '../../../utils/uuid';\r\n\r\ninterface MultiSelectDataItem {\r\n text: string;\r\n}\r\n\r\n// A very basic wrapped Kendo multiselect element that we can use independently of Formik\r\nconst BTMultiSelect: React.FC = (props) => {\r\n const [inputIdentifier] = useState(\r\n props.id || props.name || props.label || generateUuid(),\r\n );\r\n\r\n const [filteredData, setFilteredData] = useState(\r\n sortBy((props.data || []) as MultiSelectDataItem[], (v) => v.text),\r\n );\r\n\r\n const getFilteredData = (filter: FilterDescriptor | CompositeFilterDescriptor) => {\r\n const data = sortBy([...(props.data || [])], (v) => v.text);\r\n return filterBy(data, filter);\r\n };\r\n\r\n return (\r\n
    \r\n
    \r\n \r\n
    \r\n\r\n {\r\n setFilteredData(getFilteredData(e.filter));\r\n }}\r\n data={filteredData}\r\n ref={(e) => {\r\n if (inputIdentifier && e?.element && !e.element.getAttribute('data-testid')) {\r\n e.element.setAttribute('data-testid', inputIdentifier);\r\n }\r\n }}\r\n />\r\n
    \r\n );\r\n};\r\n\r\nexport default BTMultiSelect;\r\n","import lodash from 'lodash';\r\nimport React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { UserRolesValues } from '../../../../../constants/users/user-roles';\r\nimport { AuthenticationService } from '../../../../../services/authentication/authentication-service';\r\nimport { areTrimmedStringsEqual, getEmailWithoutDomain } from '../../../../../utils/strings';\r\nimport BTMultiSelect from '../../../../common-page-components/inputs/BTMultiSelect';\r\nimport ProjectErrorDisplay from './ProjectErrorDisplay';\r\n\r\ninterface Props {\r\n permissions: ProjectPermissions;\r\n users: User[];\r\n errorId: string;\r\n errors: ProjectError[];\r\n updatePermissions: (permissions: ProjectPermissions) => void;\r\n}\r\n\r\n// This component handles display of the permissions section when adding or editing a project\r\nconst AddEditPermissions: React.FC = ({\r\n permissions,\r\n users,\r\n errorId,\r\n errors,\r\n updatePermissions,\r\n}) => {\r\n const { t } = useTranslation();\r\n\r\n const generateUserOptionsByRole = (role: string): BTMultiSelectOption[] => {\r\n return lodash(users)\r\n .filter((u) => u.roles.find((v) => v.id === role) !== undefined) // Filter the users down by role\r\n .groupBy((u) => u.name?.toLowerCase()) // Group by name to find duplicates\r\n .flatMap((users) => {\r\n const isDupe = users.length > 1;\r\n\r\n return users.map((u) => {\r\n let name;\r\n if (u.name) {\r\n // For users with duplicate names, display their email as well (without the domain)\r\n name = !isDupe ? u.name : `${u.name} (${getEmailWithoutDomain(u.email)})`;\r\n } else {\r\n name = getEmailWithoutDomain(u.email);\r\n }\r\n\r\n return {\r\n id: u.email,\r\n name: name,\r\n };\r\n });\r\n })\r\n .orderBy((opt) => opt.name.toLowerCase())\r\n .value();\r\n };\r\n\r\n const projectAdminOptions = generateUserOptionsByRole(UserRolesValues.ProjectAdmin);\r\n const contributorOptions = generateUserOptionsByRole(UserRolesValues.Contributor);\r\n\r\n return (\r\n <>\r\n {permissions && (\r\n <>\r\n
    \r\n
    \r\n \r\n permissions.projectAdmins.includes(opts.id),\r\n )}\r\n onChange={(event) => {\r\n const projectAdmins = event.target.value as BTMultiSelectOption[];\r\n if (\r\n !projectAdmins.find((admin) =>\r\n areTrimmedStringsEqual(\r\n admin.id,\r\n AuthenticationService.currentUserInfo?.email,\r\n ),\r\n )\r\n ) {\r\n // The admin user creating the project should be unable to de-select their user from the list\r\n return;\r\n }\r\n const updatedPermissions: ProjectPermissions = {\r\n ...permissions,\r\n projectAdmins: projectAdmins.map((a) => a.id),\r\n };\r\n updatePermissions(updatedPermissions);\r\n }}\r\n />\r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n permissions.contributors.includes(opts.id),\r\n )}\r\n onChange={(event) => {\r\n const contributors = event.target.value as BTMultiSelectOption[];\r\n const updatedPermissions: ProjectPermissions = {\r\n ...permissions,\r\n contributors: contributors.map((c) => c.id),\r\n };\r\n updatePermissions(updatedPermissions);\r\n }}\r\n />\r\n
    \r\n
    \r\n \r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\nexport default AddEditPermissions;\r\n","import { DatePicker, DatePickerProps } from '@progress/kendo-react-dateinputs';\r\nimport React, { useState } from 'react';\r\nimport { generateUuid } from '../../../utils/uuid';\r\n\r\n// A very basic wrapped Kendo datepicker element that we can use independently of Formik\r\nconst BTDatePicker: React.FC = (props) => {\r\n const [inputIdentifier] = useState(props.id || props.name || generateUuid());\r\n\r\n return (\r\n
    \r\n
    \r\n \r\n
    \r\n\r\n {\r\n if (inputIdentifier && e?.element && !e.element.getAttribute('data-testid')) {\r\n e.element.setAttribute('data-testid', inputIdentifier);\r\n }\r\n }}\r\n />\r\n
    \r\n );\r\n};\r\n\r\nexport default BTDatePicker;\r\n","import { UploadFileInfo } from '@progress/kendo-react-upload';\r\nimport React, { useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport EntityValidationConstants from '../../../../../constants/general/entity-validation-constants';\r\nimport BTIconButton from '../../../../common-page-components/controls/icon-button/BTIconButton';\r\nimport BTDatePicker from '../../../../common-page-components/inputs/BTDatePicker';\r\nimport BTDropDownList from '../../../../common-page-components/inputs/BTDropDownList';\r\nimport BTInput from '../../../../common-page-components/inputs/BTInput';\r\nimport BTSwitch from '../../../../common-page-components/inputs/BTSwitch';\r\nimport BTUpload from '../../../../common-page-components/upload/BTUpload';\r\nimport defaultProjectImage from './../../../../assets/images/default-project-image.png';\r\nimport BTNumericInput from './../../../../common-page-components/inputs/BTNumericInput';\r\nimport './AddEditProjectInformation.scss';\r\nimport ProjectErrorDisplay from './ProjectErrorDisplay';\r\nimport { ProjectApi } from '../../../../../services';\r\nimport { NotificationPanelContext } from '../../../../common-page-components/notification-panel/NotificationPanelContext';\r\n\r\ninterface Props {\r\n userCanEditImage: boolean;\r\n projectInformation: ProjectInfo;\r\n unitsOfMeasure: string[];\r\n errorId: string;\r\n errors: ProjectError[];\r\n updateProjectInformation: (projectInformation: ProjectInfo) => void;\r\n}\r\n\r\n// This component handles display of the project information section and related errors when adding or editing a project\r\nconst AddEditProjectInformation: React.FC = ({\r\n userCanEditImage,\r\n projectInformation,\r\n unitsOfMeasure,\r\n errorId,\r\n errors,\r\n updateProjectInformation,\r\n}) => {\r\n const { t } = useTranslation();\r\n const [imageUrl, setImageUrl] = useState();\r\n const [projectImageBlobUrl, setProjectImageBlobUrl] = useState();\r\n const currentProjectImageUri = useRef();\r\n const { showErrorNotification } = useContext(NotificationPanelContext);\r\n\r\n useEffect(() => {\r\n setImageUrl(\r\n projectInformation.image !== null ? URL.createObjectURL(projectInformation.image) : null,\r\n );\r\n }, [projectInformation.image]);\r\n\r\n useEffect(() => {\r\n const getProjectImageUrl = async () => {\r\n if (currentProjectImageUri.current !== projectInformation.imageUri) {\r\n if (projectInformation.imageUri) {\r\n // Fetch the latest project image if there is one\r\n try {\r\n const imageBlobUrl = await ProjectApi.getProjectImageBlobUrl(\r\n projectInformation.id,\r\n projectInformation.imageUri,\r\n );\r\n\r\n setProjectImageBlobUrl(imageBlobUrl);\r\n } catch (error) {\r\n showErrorNotification(t('general:error'), t('project:projectImageLoadError'));\r\n }\r\n } else {\r\n // Clear the blob url because the project image may be removed or never set\r\n setProjectImageBlobUrl(null);\r\n }\r\n\r\n currentProjectImageUri.current = projectInformation.imageUri;\r\n }\r\n };\r\n\r\n getProjectImageUrl();\r\n }, [\r\n projectImageBlobUrl,\r\n projectInformation.id,\r\n projectInformation.imageUri,\r\n showErrorNotification,\r\n t,\r\n ]);\r\n\r\n const unitOfMeasureOptions = [\r\n ...unitsOfMeasure.map((u) => {\r\n return {\r\n name: u,\r\n value: u,\r\n };\r\n }),\r\n { name: '', value: null },\r\n ];\r\n\r\n return (\r\n <>\r\n {projectInformation && (\r\n
    \r\n
    \r\n
    \r\n {\r\n const newValue = event.value;\r\n\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n isHardBid: newValue,\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n />\r\n\r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n name: event.value,\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.Name_MaxLength}\r\n />\r\n
    \r\n\r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n subtitle: event.value,\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.Subtitle_MaxLength}\r\n />\r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n \r\n\r\n {userCanEditImage ? (\r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n image: null,\r\n imageUri: '',\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n data-testid={'delete-project-image-data-testid'}\r\n disabled={\r\n (projectInformation.imageUri === '' ||\r\n projectInformation.imageUri === null) &&\r\n projectInformation.image === null\r\n }\r\n />\r\n ) : (\r\n <>\r\n )}\r\n
    \r\n\r\n
    \r\n
    \r\n\r\n {!userCanEditImage ? (\r\n \r\n {t('project:projectImageCannotBeEdited')}\r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {userCanEditImage ? (\r\n {\r\n if (!files) {\r\n return;\r\n }\r\n const fileObj = files[0];\r\n const file = fileObj.getRawFile!();\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n image: file,\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n />\r\n ) : (\r\n <>\r\n )}\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n siteAddress: {\r\n ...projectInformation.siteAddress,\r\n streetAddress: event.value,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.StreetAddress_MaxLength}\r\n />\r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n siteAddress: {\r\n ...projectInformation.siteAddress,\r\n aptSuiteBldg: event.value,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.AptSuiteBldg_MaxLength}\r\n />\r\n
    \r\n
    \r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n siteAddress: {\r\n ...projectInformation.siteAddress,\r\n city: event.value,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.City_MaxLength}\r\n />\r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n siteAddress: {\r\n ...projectInformation.siteAddress,\r\n stateOrRegion: event.value,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.StateOrRegion_MaxLength}\r\n />\r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n siteAddress: {\r\n ...projectInformation.siteAddress,\r\n postalCode: event.value,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.PostalCode_MaxLength}\r\n />\r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n siteAddress: {\r\n ...projectInformation.siteAddress,\r\n country: event.value,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.Country_MaxLength}\r\n />\r\n
    \r\n
    \r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n bidDueDate: event.value,\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n />\r\n
    \r\n\r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n startDate: event.value,\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n />\r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n completionDate: event.value,\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n />\r\n
    \r\n
    \r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n owner: event.value,\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.Owner_MaxLength}\r\n />\r\n
    \r\n
    \r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n architect: event.value,\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n maxLength={EntityValidationConstants.ProjectEntityLimits.Architect_MaxLength}\r\n />\r\n
    \r\n
    \r\n
    \r\n
    \r\n {\r\n const newValue =\r\n typeof inputElement.target.value === 'number'\r\n ? (inputElement.target.value as number)\r\n : null;\r\n\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n totalBuildingArea: {\r\n ...projectInformation.totalBuildingArea,\r\n quantity: newValue,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n />\r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n totalBuildingArea: {\r\n ...projectInformation.totalBuildingArea,\r\n unitOfMeasure: value as string | null,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n />\r\n
    \r\n\r\n
    \r\n {\r\n const newValue =\r\n typeof inputElement.target.value === 'number'\r\n ? (inputElement.target.value as number)\r\n : null;\r\n\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n totalSiteArea: {\r\n ...projectInformation.totalSiteArea,\r\n quantity: newValue,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n />\r\n
    \r\n
    \r\n {\r\n const updatedProjectInfo: ProjectInfo = {\r\n ...projectInformation,\r\n totalSiteArea: {\r\n ...projectInformation.totalSiteArea,\r\n unitOfMeasure: value as string,\r\n },\r\n };\r\n updateProjectInformation(updatedProjectInfo);\r\n }}\r\n />\r\n
    \r\n
    \r\n \r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\nexport default AddEditProjectInformation;\r\n","import { CommandManagerService } from '../../../../../services/command/command-manager-service';\r\nimport { addCommandToBatchCommandObject } from '../../../../../utils/command-manager-service';\r\n\r\nconst addEditProjectReducer: DispatchManagerReducer<\r\n CommandManagerService,\r\n DispatchManagerDispatchActions_AddEditProject\r\n> = (\r\n dispatchData: CommandManagerService,\r\n action: DispatchManagerDispatchAction,\r\n): CommandManagerService => {\r\n switch (action.type) {\r\n case 'create-project':\r\n return addCommandToBatchCommandObject(dispatchData, action.data as ICommand);\r\n\r\n default:\r\n return dispatchData;\r\n }\r\n};\r\n\r\nexport default addEditProjectReducer;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport { AxiosError, AxiosResponse } from 'axios';\r\nimport { cloneDeep, groupBy, isEqual, sortBy, uniq } from 'lodash';\r\nimport React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useHistory, useRouteMatch } from 'react-router';\r\nimport { Collapse } from 'reactstrap';\r\nimport { CreateProjectCommand } from '../../../../classes/commands/project/create-project-command';\r\nimport { UpdateProjectCommand } from '../../../../classes/commands/project/update-project-command';\r\nimport { BidPackage } from '../../../../classes/odata/bid-package';\r\nimport GeneralConstants from '../../../../constants/general';\r\nimport ApplicationRoutes from '../../../../constants/routes';\r\nimport useCommandManagerDispatcher from '../../../../hooks/dispatch-manager-helper/useDispatcherWithCommandManagerService';\r\nimport {\r\n BidPackageMaintenanceApi,\r\n FeeApi,\r\n FrozenEntitiesApi,\r\n GeneralRequirementsApi,\r\n ProjectApi,\r\n UnitOfMeasureApi,\r\n UserApi,\r\n} from '../../../../services';\r\nimport { AuthenticationService } from '../../../../services/authentication/authentication-service';\r\nimport { useLogger } from '../../../../services/logger/Logger';\r\nimport { NotificationService } from '../../../../services/notification/notification-service';\r\nimport { convertFeeTypeToFeeTypeName } from '../../../../utils/feeLabel';\r\nimport { scrollToRef } from '../../../../utils/general';\r\nimport { navigateBack } from '../../../../utils/navigation-helpers';\r\nimport { areTrimmedStringsEqual, getDuplicates } from '../../../../utils/strings';\r\nimport { isValidUuid } from '../../../../utils/uuid';\r\nimport { ConfirmationOverlayContext } from '../../../common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport BTButton from '../../../common-page-components/controls/button/BTButton';\r\nimport FrozenEntityNotification from '../../../common-page-components/frozen-entity-notification/FrozenEntityNotification';\r\nimport { BTGeneralContext } from '../../../common-page-components/general-contexts/BTGeneralContext';\r\nimport { LoadingPageOverlayContext } from '../../../common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport { NotificationPanelContext } from '../../../common-page-components/notification-panel/NotificationPanelContext';\r\nimport PageHeader from '../../../common-page-components/page-header/PageHeader';\r\nimport { FeeTypes } from '../../../enums/fee-enum';\r\nimport useCommandServiceHelper from '../../../shared-page-components/hooks/useCommandServiceHelper';\r\nimport useDegradedActionNotifications from '../../../shared-page-components/hooks/useDegradedActionNotifications';\r\nimport AddEditAlternates from './components/AddEditAlternates';\r\nimport AddEditBidPackages from './components/AddEditBidPackages';\r\nimport AddEditFees from './components/AddEditFees';\r\nimport AddEditGeneralRequirements from './components/AddEditGeneralRequirements';\r\nimport AddEditPermissions from './components/AddEditPermissions';\r\nimport AddEditProjectInformation from './components/AddEditProjectInformation';\r\nimport './ProjectPage.scss';\r\nimport addEditProjectReducer from './reducers/add-edit-project-reducer';\r\n\r\nconst projectPageDispatcherKey = 'Add-Edit-Project-Group-Id';\r\n\r\nconst Project_Image_File_MaxSize = 20 * 1_000_000;\r\n\r\nconst emptySiteAddress: Address = {\r\n streetAddress: '',\r\n aptSuiteBldg: '',\r\n city: '',\r\n stateOrRegion: '',\r\n postalCode: '',\r\n country: '',\r\n};\r\n\r\nconst emptyProjectInformation: ProjectInfo = {\r\n id: '',\r\n name: '',\r\n subtitle: '',\r\n siteAddress: emptySiteAddress,\r\n bidDueDate: new Date(),\r\n startDate: null,\r\n completionDate: null,\r\n owner: '',\r\n architect: '',\r\n projectAdmins: '',\r\n contributors: '',\r\n totalBuildingArea: {\r\n quantity: null,\r\n unitOfMeasure: '',\r\n },\r\n totalSiteArea: {\r\n quantity: null,\r\n unitOfMeasure: '',\r\n },\r\n isHardBid: false,\r\n image: null,\r\n imageUri: '',\r\n lineItemRollup1: '',\r\n lineItemRollup2: '',\r\n alternates: [],\r\n};\r\n\r\nconst ProjectPage: React.FC = () => {\r\n const { t } = useTranslation();\r\n const history = useHistory();\r\n const logger = useLogger();\r\n\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n const { showInfoNotification, showSuccessNotification, showErrorNotification } = useContext(\r\n NotificationPanelContext,\r\n );\r\n\r\n const { signalRResponseTimeout } = useContext(BTGeneralContext);\r\n\r\n const { executeCommand } = useCommandServiceHelper();\r\n\r\n const [project, setProject] = useState();\r\n const newProjectId = useRef();\r\n\r\n const [projectNames, setProjectNames] = useState([]);\r\n const [projectToEdit, setProjectToEdit] = useState();\r\n const [unitsOfMeasure, setUnitsOfMeasure] = useState([]);\r\n const [users, setUsers] = useState();\r\n const [isNew, setIsNew] = useState(true);\r\n const [errors, setErrors] = useState([]);\r\n const [isProcessing, setIsProcessing] = useState(false);\r\n const isValid = errors.length === 0;\r\n const projectInformationRef = useRef(null);\r\n\r\n const [bidPackageIdsThatAreFrozen, setBidPackageIdsThatAreFrozen] = useState([]);\r\n const [projectUploadContainerIdIsFrozen, setProjectUploadContainerIdIsFrozen] = useState(\r\n false,\r\n );\r\n\r\n // Collapsible sections\r\n const [isBidPackagesAreaOpen, setIsBidPackagesAreaOpen] = useState(true);\r\n const [isGeneralRequirementsAreaOpen, setIsGeneralRequirementsAreaOpen] = useState(true);\r\n const [isAlternatesAreaOpen, setIsAlternatesAreaOpen] = useState(true);\r\n const [isFeesAreaOpen, setIsFeesAreaOpen] = useState(true);\r\n const [isPermissionsAreaOpen, setIsPermissionsAreaOpen] = useState(true);\r\n const [isLoaded, setIsLoaded] = useState(false);\r\n\r\n const projectInfoErrorId = 'project-info-error';\r\n const bidPackagesErrorId = 'bid-packages-error';\r\n const feesErrorId = 'fees-error';\r\n const alternatesErrorId = 'alternates-error';\r\n const permissionsErrorId = 'permissions-error';\r\n\r\n const duplicateAlternateError = t('project:duplicateAlternateError');\r\n const emptyAlternateError = t('project:emptyAlternateError');\r\n const projectNameRequiredError = t('project:nameRequiredError');\r\n const oneBidPackageRequiredError = t('project:oneBidPackageRequiredError');\r\n const projectDateError = t('project:projectDateError');\r\n const projectBidDueDateError = t('project:projectBidDueDateError');\r\n const projectImageTypeError = t('project:projectImageTypeError');\r\n const projectImageSizeError = t('project:projectImageSizeError');\r\n const unitOfMeasureWithoutTotalBuildingAreaError = t(\r\n 'project:unitOfMeasureWithoutTotalBuildingAreaError',\r\n );\r\n const unitOfMeasureWithoutTotalSiteAreaError = t(\r\n 'project:unitOfMeasureWithoutTotalSiteAreaError',\r\n );\r\n\r\n const projectName = project?.information.name ?? '';\r\n const bidPackageIds = useMemo(() => project?.bidPackages.map((bp) => bp.id) ?? [], [\r\n project?.bidPackages,\r\n ]);\r\n const projectId =\r\n useRouteMatch(`${ApplicationRoutes.PROJECT}/:projectId?`)?.params\r\n .projectId || '';\r\n\r\n const isDirty = useMemo(() => {\r\n const informationChanged = !isEqual(project?.information, projectToEdit?.information);\r\n const bidPackagesChanged = !isEqual(project?.bidPackages, projectToEdit?.bidPackages);\r\n const generalRequirementsChanged = !isEqual(\r\n project?.generalRequirements,\r\n projectToEdit?.generalRequirements,\r\n );\r\n const alternatesChanged = !isEqual(\r\n project?.alternates.map((alternate) => alternate.name).sort(),\r\n projectToEdit?.alternates.map((alternate) => alternate.name).sort(),\r\n );\r\n const feesChanged = !isEqual(project?.fees, projectToEdit?.fees);\r\n const permissionsChanged = !isEqual(project?.permissions, projectToEdit?.permissions);\r\n\r\n // If any parts of the project have been changed, return true\r\n if (\r\n informationChanged ||\r\n bidPackagesChanged ||\r\n generalRequirementsChanged ||\r\n alternatesChanged ||\r\n feesChanged ||\r\n permissionsChanged\r\n ) {\r\n return true;\r\n }\r\n return false;\r\n }, [project, projectToEdit]);\r\n\r\n // Initialize Command Manager Service\r\n const {\r\n initializeCommandManagerServiceOnDispatcher,\r\n //commandManagerService,\r\n } = useCommandManagerDispatcher({ key: projectPageDispatcherKey });\r\n\r\n // Initial load of data\r\n useEffect(() => {\r\n const loadInitialData = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // Check the frozen state of the system settings\r\n const systemSettingsEntityIsFrozen = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n GeneralConstants.ENTITY_IDS.SYSTEM_SETTINGS,\r\n );\r\n\r\n // If the system entity is frozen, it affects various things on the project so rather than piecemeal\r\n // we do not let the user add or edit projects\r\n if (systemSettingsEntityIsFrozen) {\r\n showErrorNotification(t('general:error'), t('project:systemSettingsIsFrozen'));\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n return;\r\n }\r\n\r\n if (!projectId) {\r\n // Create a new project\r\n\r\n // Fetch auxiliary data collections\r\n const [\r\n basicProjectData,\r\n unitOfMeasureData,\r\n generalConditionsData,\r\n bidPackageData,\r\n generalRequirementData,\r\n feeData,\r\n userData,\r\n ] = await Promise.all([\r\n ProjectApi.getAllProjectInfos(),\r\n UnitOfMeasureApi.getAllUnitsOfMeasure(),\r\n BidPackageMaintenanceApi.getGeneralConditionsDefinition(),\r\n BidPackageMaintenanceApi.getAllBidPackageDefinitions(),\r\n GeneralRequirementsApi.getAllGeneralRequirementDefinitions(),\r\n FeeApi.getFeeDefinitions(),\r\n UserApi.getAllUsers(),\r\n ]);\r\n\r\n setProjectNames(basicProjectData.map((bpd) => bpd.name.toLowerCase()));\r\n setUnitsOfMeasure(unitOfMeasureData.map((uom) => uom.name ?? ''));\r\n setUsers(userData);\r\n\r\n // If it exists, insert the generalConditions package into the first index of the bidPackageData collection\r\n if (generalConditionsData) {\r\n bidPackageData.unshift(generalConditionsData);\r\n }\r\n\r\n const projectData: ProjectData = {\r\n information: emptyProjectInformation,\r\n bidPackages: sortBy(bidPackageData, (bp) => bp.code).map((bp) => {\r\n return {\r\n id: bp.id,\r\n code: bp.code,\r\n description: bp.description,\r\n requirements: [],\r\n assignedToUser: null,\r\n assignedToUserId: null,\r\n isSelected: true,\r\n };\r\n }),\r\n generalRequirements: sortBy(generalRequirementData, (gr) => gr.index).map((gr) => {\r\n return {\r\n id: gr.id,\r\n description: gr.description,\r\n isSelected: true,\r\n };\r\n }),\r\n alternates: [],\r\n fees: sortBy(feeData, (f) => f.order).map((f) => {\r\n return {\r\n id: f.id,\r\n name: f.name,\r\n order: f.order,\r\n amount: f.amount,\r\n feeType: f.feeType,\r\n feeTypeName: convertFeeTypeToFeeTypeName(t, f.feeType!, f.referenceFeeName),\r\n referenceFeeName: f.referenceFeeName,\r\n isSelected: true,\r\n };\r\n }),\r\n permissions: {\r\n projectAdmins: AuthenticationService.currentUserInfo\r\n ? [AuthenticationService.currentUserInfo.email]\r\n : [],\r\n contributors: [],\r\n },\r\n };\r\n setProject(projectData);\r\n setProjectToEdit(projectData);\r\n } else {\r\n // Edit an existing project\r\n if (!isValidUuid(projectId)) {\r\n throw new Error('The project ID parameter was not found or was invalid.');\r\n }\r\n setIsNew(false);\r\n\r\n // Check the frozen state of the project entity\r\n const projectIsFrozenResult = await FrozenEntitiesApi.checkIfEntityIsFrozen(projectId);\r\n\r\n // If the project is frozen, we don't want to show a banner like we do on other pages.\r\n // Since this is the project edit page, we should not have been able to get here in the first place\r\n // due to restrictions in the UI elsewhere so we just show the user an error message and redirect\r\n // them to the error page.\r\n if (projectIsFrozenResult) {\r\n showErrorNotification(t('general:error'), t('project:projectIsFrozen'));\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n return;\r\n }\r\n\r\n // Fetch auxiliary data collections\r\n const [\r\n allBasicProjectInfoData,\r\n allUnitOfMeasureData,\r\n allGeneralConditionData,\r\n allBidPackageData,\r\n allGeneralRequirementData,\r\n allFeeData,\r\n allUserData,\r\n ] = await Promise.all([\r\n ProjectApi.getAllProjectInfos(),\r\n UnitOfMeasureApi.getAllUnitsOfMeasure(),\r\n BidPackageMaintenanceApi.getGeneralConditionsDefinition(),\r\n BidPackageMaintenanceApi.getAllBidPackageDefinitions(),\r\n GeneralRequirementsApi.getAllGeneralRequirementDefinitions(),\r\n FeeApi.getFeeDefinitions(),\r\n UserApi.getAllUsers(),\r\n ]);\r\n\r\n // Fetch current project data collections\r\n const [\r\n currentProjectDetailedInfo,\r\n currentProjectBidPackagesCollection,\r\n currentProjectAlternatesCollection,\r\n currentProjectFeesCollection,\r\n ] = await Promise.all([\r\n ProjectApi.getProjectInfoById(projectId),\r\n ProjectApi.getBidPackagesByProjectId(projectId),\r\n ProjectApi.getAlternatesByProjectId(projectId),\r\n ProjectApi.getFeesByProjectId(projectId),\r\n ]);\r\n\r\n if (!currentProjectDetailedInfo) {\r\n throw new Error(t('project:projectInfoNotFoundError', { id: projectId }));\r\n }\r\n\r\n // Check the frozen status of the bid packages on this project\r\n const bidPackageIds = currentProjectBidPackagesCollection.map((v) => v.id);\r\n\r\n const bidPackageIdsPromisesArray: Promise[] = bidPackageIds.map((v) =>\r\n FrozenEntitiesApi.checkIfEntityIsFrozen(v),\r\n );\r\n\r\n const bidPackageIdsResults = await Promise.all(bidPackageIdsPromisesArray);\r\n const frozenBidPackageIds: string[] = [];\r\n\r\n bidPackageIdsResults.forEach((v, i) => {\r\n if (v) {\r\n frozenBidPackageIds.push(bidPackageIds[i]);\r\n }\r\n });\r\n\r\n setBidPackageIdsThatAreFrozen(frozenBidPackageIds);\r\n\r\n // Check the frozen status of the project upload container ID\r\n if (currentProjectDetailedInfo.fileUploadContainerId) {\r\n const fileUploadContainerIdResult = await FrozenEntitiesApi.checkIfEntityIsFrozen(\r\n currentProjectDetailedInfo.fileUploadContainerId,\r\n );\r\n\r\n setProjectUploadContainerIdIsFrozen(fileUploadContainerIdResult);\r\n }\r\n\r\n // Set auxiliary data used in the form\r\n setProjectNames(\r\n allBasicProjectInfoData\r\n .filter((bpd) => bpd.id !== projectId)\r\n .map((bpd) => bpd.name.toLowerCase()),\r\n );\r\n setUnitsOfMeasure(allUnitOfMeasureData.map((uom) => uom.name ?? ''));\r\n setUsers(allUserData);\r\n\r\n // If it exists, insert the generalConditions package into the first index of the bidPackageData collection\r\n if (allGeneralConditionData) {\r\n allBidPackageData.unshift(allGeneralConditionData);\r\n }\r\n\r\n // Populate Project Package info\r\n const currentProjectInfo: ProjectInfo = {\r\n id: currentProjectDetailedInfo.id,\r\n name: currentProjectDetailedInfo.name,\r\n subtitle: currentProjectDetailedInfo.subtitle,\r\n bidDueDate:\r\n currentProjectDetailedInfo.bidDueDate !== null\r\n ? new Date(currentProjectDetailedInfo.bidDueDate as Date)\r\n : new Date(),\r\n siteAddress: currentProjectDetailedInfo.siteAddress || emptySiteAddress,\r\n startDate:\r\n currentProjectDetailedInfo.startDate !== null\r\n ? new Date(currentProjectDetailedInfo.startDate as Date)\r\n : null,\r\n completionDate:\r\n currentProjectDetailedInfo.completionDate !== null\r\n ? new Date(currentProjectDetailedInfo.completionDate as Date)\r\n : null,\r\n owner: currentProjectDetailedInfo.owner,\r\n architect: currentProjectDetailedInfo.architect,\r\n projectAdmins: currentProjectDetailedInfo.projectAdmins,\r\n contributors: currentProjectDetailedInfo.contributors,\r\n totalBuildingArea: {\r\n quantity: currentProjectDetailedInfo.totalBuildingArea,\r\n unitOfMeasure: currentProjectDetailedInfo.totalBuildingAreaUnitOfMeasure,\r\n },\r\n totalSiteArea: {\r\n quantity: currentProjectDetailedInfo.totalSiteArea,\r\n unitOfMeasure: currentProjectDetailedInfo.totalSiteAreaUnitOfMeasure,\r\n },\r\n isHardBid: currentProjectDetailedInfo.isHardBid,\r\n image: null,\r\n imageUri: currentProjectDetailedInfo.imageUri,\r\n lineItemRollup1: '',\r\n lineItemRollup2: '',\r\n alternates: [],\r\n };\r\n\r\n // Populate Bid Packages section.\r\n // Step 1: get the bid packages already in the project.\r\n let currentProjectBidPackages = currentProjectBidPackagesCollection.map(\r\n (bp): ProjectBidPackage => {\r\n const bidPackageUser = allUserData?.find((u) => u.id === bp?.assignedToUserId);\r\n return {\r\n id: bp.id,\r\n code: bp.code,\r\n description: bp.description ? bp.description : '',\r\n assignedToUser: bidPackageUser != null ? bidPackageUser.email : null,\r\n assignedToUserId: bidPackageUser != null ? bidPackageUser.id : null,\r\n isSelected: true,\r\n };\r\n },\r\n );\r\n\r\n // Step 2: find bid package definitions that aren't already included.\r\n allBidPackageData.forEach((bpd) => {\r\n const currentBidPackage = currentProjectBidPackagesCollection.find(\r\n (bp) => bp.code === bpd.code,\r\n );\r\n if (!areTrimmedStringsEqual(bpd.description, currentBidPackage?.description, true)) {\r\n currentProjectBidPackages.push({\r\n id: bpd.id,\r\n code: bpd.code,\r\n description: bpd.description,\r\n assignedToUser: null,\r\n assignedToUserId: null,\r\n isSelected: false,\r\n });\r\n }\r\n });\r\n\r\n // Step 3: sort the array.\r\n currentProjectBidPackages = sortBy(currentProjectBidPackages, (pbp) => pbp.code);\r\n\r\n // Populate the General Requirements section\r\n // Step 1: get the unique general requirements already in the project.\r\n const currentProjectGRs: {\r\n id: string | undefined;\r\n description: string | undefined;\r\n order: number | undefined;\r\n isSelected: boolean;\r\n }[] = [];\r\n currentProjectBidPackagesCollection.forEach((bp) => {\r\n BidPackage.getGeneralRequirements(bp.requirements).forEach((bpr) => {\r\n if (\r\n !currentProjectGRs.find((gr) =>\r\n areTrimmedStringsEqual(gr.description, bpr.description, true),\r\n )\r\n ) {\r\n currentProjectGRs.push({\r\n id: bpr.id,\r\n description: bpr.description,\r\n order: bpr.order,\r\n isSelected: true,\r\n });\r\n }\r\n });\r\n });\r\n\r\n // Step 2: find bid package definitions that aren't already included.\r\n allGeneralRequirementData.forEach((gr) => {\r\n const currentGR = currentProjectGRs.find((cgr) =>\r\n areTrimmedStringsEqual(cgr.description, gr.description, true),\r\n );\r\n if (!currentGR) {\r\n currentProjectGRs.push({\r\n id: gr.id,\r\n description: gr.description,\r\n order: gr.index,\r\n isSelected: false,\r\n });\r\n }\r\n });\r\n\r\n // Step 3: sort and pare down the array.\r\n const currentProjectGeneralRequirements = sortBy(currentProjectGRs, (gr) => gr.order).map(\r\n (gr): ProjectGeneralRequirement => {\r\n return {\r\n id: gr.id ? gr.id : '',\r\n description: gr.description ? gr.description : '',\r\n isSelected: gr.isSelected,\r\n };\r\n },\r\n );\r\n\r\n // Populate the Fees section\r\n // Step 1: get the fees already in the project.\r\n let currentProjectFees = currentProjectFeesCollection.map(\r\n (fee): ProjectFee => {\r\n return {\r\n id: fee.id,\r\n name: fee.name,\r\n order: fee.order,\r\n amount: fee.amount,\r\n feeType: fee.feeType,\r\n feeTypeName: convertFeeTypeToFeeTypeName(t, fee.feeType!, fee.referenceFeeName),\r\n referenceFeeName: fee.referenceFeeName,\r\n isSelected: true,\r\n };\r\n },\r\n );\r\n\r\n // Step 2: find fee definitions that aren't already included.\r\n allFeeData.forEach((fd) => {\r\n const currentFee = currentProjectFees.find(\r\n (fee) =>\r\n areTrimmedStringsEqual(fee.name, fd.name, true) &&\r\n areTrimmedStringsEqual(fee.referenceFeeName, fd.referenceFeeName, true) &&\r\n fee.feeType === fd.feeType,\r\n );\r\n if (!currentFee) {\r\n currentProjectFees.push({\r\n id: fd.id,\r\n name: fd.name,\r\n order: fd.order,\r\n amount: fd.amount,\r\n feeType: fd.feeType,\r\n feeTypeName: convertFeeTypeToFeeTypeName(t, fd.feeType!, fd.referenceFeeName),\r\n referenceFeeName: fd.referenceFeeName,\r\n isSelected: false,\r\n });\r\n }\r\n });\r\n\r\n // Step 3: sort the array.\r\n currentProjectFees = sortBy(currentProjectFees, (fee) => fee.order);\r\n\r\n // Populate the Permissions section\r\n const currentProjectAdmins: string[] = [];\r\n if (currentProjectDetailedInfo.projectAdmins && allUserData) {\r\n allUserData.forEach((user) => {\r\n if (currentProjectDetailedInfo.projectAdmins!.includes(user.email)) {\r\n currentProjectAdmins.push(user.email);\r\n }\r\n });\r\n }\r\n const currentContributors: string[] = [];\r\n if (currentProjectDetailedInfo.contributors && allUserData) {\r\n allUserData.forEach((user) => {\r\n if (currentProjectDetailedInfo.contributors!.includes(user.email)) {\r\n currentContributors.push(user.email);\r\n }\r\n });\r\n }\r\n const currentProjectPermissions: ProjectPermissions = {\r\n projectAdmins: currentProjectAdmins,\r\n contributors: currentContributors,\r\n };\r\n\r\n const sortedAlternates = sortBy(\r\n currentProjectAlternatesCollection,\r\n (alternate) => alternate.name,\r\n );\r\n const projectData: ProjectData = {\r\n information: currentProjectInfo,\r\n bidPackages: currentProjectBidPackages,\r\n generalRequirements: currentProjectGeneralRequirements,\r\n alternates: sortedAlternates,\r\n fees: currentProjectFees,\r\n permissions: currentProjectPermissions,\r\n };\r\n setProject(projectData);\r\n setProjectToEdit(cloneDeep(projectData));\r\n }\r\n setIsLoaded(true);\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(t('general:error'), t('project:failedToLoadTheProject'));\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n loadInitialData();\r\n }, [\r\n hidePageLoadingOverlay,\r\n history,\r\n projectId,\r\n showErrorNotification,\r\n showPageLoadingOverlay,\r\n t,\r\n logger,\r\n ]);\r\n\r\n useDegradedActionNotifications('ProjectPage');\r\n\r\n // Reroute on successful project creation or update\r\n useEffect(() => {\r\n NotificationService.onAllEventsForCommandProcessed((message) => {\r\n logger.logDebug('ProjectPage.onAllEventsForCommandProcessed', message);\r\n\r\n const projectIdForRedirect = (isNew ? newProjectId.current : projectId) || '';\r\n\r\n // Ignore messages for other entities\r\n const projectAndBidPackageIds = [projectIdForRedirect, ...bidPackageIds];\r\n const matches = message.SourceIds.filter((id) => projectAndBidPackageIds.includes(id));\r\n if (!matches) {\r\n return;\r\n }\r\n\r\n if (signalRResponseTimeout.current) {\r\n clearTimeout(signalRResponseTimeout.current);\r\n signalRResponseTimeout.current = null;\r\n }\r\n\r\n hidePageLoadingOverlay(true);\r\n\r\n // If this is a new project, redirect to summary - otherwise return to the page the edit function was invoked from\r\n if (isNew) {\r\n showSuccessNotification(t('general:success'), t('project:createProjectSuccess'));\r\n history.push(`${ApplicationRoutes.BID_SUMMARY}/${projectIdForRedirect}`);\r\n } else {\r\n showSuccessNotification(t('general:success'), t('project:updateProjectSuccess'));\r\n navigateBack(history);\r\n }\r\n });\r\n\r\n return function cleanup() {\r\n NotificationService.offAllEventsForCommandProcessed();\r\n };\r\n }, [\r\n signalRResponseTimeout,\r\n hidePageLoadingOverlay,\r\n history,\r\n isNew,\r\n logger,\r\n projectId,\r\n showInfoNotification,\r\n showSuccessNotification,\r\n t,\r\n bidPackageIds,\r\n ]);\r\n\r\n // Register groupId and reducer function with the Command Manager Service\r\n useEffect(() => {\r\n initializeCommandManagerServiceOnDispatcher(projectPageDispatcherKey, addEditProjectReducer);\r\n }, [initializeCommandManagerServiceOnDispatcher]);\r\n\r\n const validateProjectInformation = useCallback(\r\n (projectInformation: ProjectInfo) => {\r\n // Clear current projectInformation errors\r\n const updatedErrors = errors.filter((e) => e.id !== projectInfoErrorId);\r\n\r\n // Check if the project name is empty or whitespace\r\n if (projectInformation.name.length === 0) {\r\n updatedErrors.push({\r\n id: projectInfoErrorId,\r\n message: projectNameRequiredError,\r\n });\r\n } else {\r\n // If it's not empty/whitespace - check if it already exists\r\n const cleanedUpName = projectInformation.name.trim().toLowerCase();\r\n let duplicateNames = [];\r\n duplicateNames = projectNames.filter(\r\n (item) => item === cleanedUpName && item !== projectName,\r\n );\r\n\r\n if (duplicateNames.length > 0) {\r\n updatedErrors.push({\r\n id: projectInfoErrorId,\r\n message: t('project:nameDuplicateError', { name: projectInformation.name }),\r\n });\r\n }\r\n }\r\n\r\n // Check if the project image is a valid file type and within size limits\r\n if (projectInformation.image) {\r\n if (!['jpeg', 'png'].includes(projectInformation.image.type.split('/').pop() || '')) {\r\n updatedErrors.push({\r\n id: projectInfoErrorId,\r\n message: projectImageTypeError,\r\n });\r\n }\r\n if (projectInformation.image.size > Project_Image_File_MaxSize) {\r\n updatedErrors.push({\r\n id: projectInfoErrorId,\r\n message: projectImageSizeError,\r\n });\r\n }\r\n }\r\n\r\n if (!projectInformation.bidDueDate) {\r\n updatedErrors.push({\r\n id: projectInfoErrorId,\r\n message: projectBidDueDateError,\r\n });\r\n }\r\n\r\n // If the project start and completion dates both have values, check if project completion date falls after project start date\r\n if (\r\n projectInformation.startDate &&\r\n projectInformation.completionDate &&\r\n projectInformation.startDate > projectInformation.completionDate\r\n ) {\r\n updatedErrors.push({\r\n id: projectInfoErrorId,\r\n message: projectDateError,\r\n });\r\n }\r\n\r\n if (\r\n projectInformation.totalBuildingArea.quantity === null &&\r\n projectInformation.totalBuildingArea.unitOfMeasure\r\n ) {\r\n updatedErrors.push({\r\n id: projectInfoErrorId,\r\n message: unitOfMeasureWithoutTotalBuildingAreaError,\r\n });\r\n }\r\n\r\n if (\r\n projectInformation.totalSiteArea.quantity === null &&\r\n projectInformation.totalSiteArea.unitOfMeasure\r\n ) {\r\n updatedErrors.push({\r\n id: projectInfoErrorId,\r\n message: unitOfMeasureWithoutTotalSiteAreaError,\r\n });\r\n }\r\n\r\n setErrors(updatedErrors);\r\n return updatedErrors.length === 0;\r\n },\r\n [\r\n errors,\r\n projectName,\r\n projectBidDueDateError,\r\n projectDateError,\r\n projectImageSizeError,\r\n projectImageTypeError,\r\n projectNameRequiredError,\r\n unitOfMeasureWithoutTotalBuildingAreaError,\r\n unitOfMeasureWithoutTotalSiteAreaError,\r\n projectNames,\r\n t,\r\n ],\r\n );\r\n\r\n const updateProjectInformation = useCallback(\r\n (projectInformation: ProjectInfo) => {\r\n if (projectToEdit) {\r\n validateProjectInformation(projectInformation);\r\n setProjectToEdit({\r\n ...projectToEdit,\r\n information: projectInformation,\r\n });\r\n }\r\n },\r\n [projectToEdit, validateProjectInformation],\r\n );\r\n\r\n const validatePermissions = useCallback(\r\n (newPermissions: ProjectPermissions) => {\r\n // Clear current permission errors\r\n const updatedErrors = errors.filter((e) => e.id !== permissionsErrorId);\r\n\r\n const previousPermissions = projectToEdit?.permissions;\r\n if (previousPermissions) {\r\n const projectAdminsToRemove = previousPermissions.projectAdmins.filter(\r\n (u) => !newPermissions.projectAdmins.includes(u),\r\n );\r\n const contributorsToRemove = previousPermissions.contributors.filter(\r\n (u) => !newPermissions.contributors.includes(u),\r\n );\r\n\r\n // If there are project admins or contributors being removed, we must\r\n // check for bid package assignment\r\n if (projectAdminsToRemove.length > 0 || contributorsToRemove.length > 0) {\r\n // Create mapping of assigned user to bid package\r\n const assignedUserToBidPackageMap = groupBy(\r\n projectToEdit?.bidPackages ?? [],\r\n (bp) => bp.assignedToUser,\r\n );\r\n\r\n // Local func for code reuse\r\n const addErrorIfUserIsAssignedToBidPackage = (userToRemove: string) => {\r\n const bidPackages = assignedUserToBidPackageMap[userToRemove];\r\n if (!bidPackages || bidPackages.length === 0) {\r\n return;\r\n }\r\n\r\n // Add error if the user is assigned to a bid package\r\n const bpCodes = bidPackages.map((bp) => bp.code);\r\n updatedErrors.push({\r\n id: permissionsErrorId,\r\n message: t('project:cannotRemoveUserPermission', {\r\n user: userToRemove,\r\n bidPackageCodes: bpCodes.join(', '),\r\n }),\r\n });\r\n };\r\n\r\n // Check project admins\r\n projectAdminsToRemove.forEach((userToRemove) => {\r\n if (!newPermissions.contributors.includes(userToRemove)) {\r\n addErrorIfUserIsAssignedToBidPackage(userToRemove);\r\n }\r\n });\r\n\r\n // Check contributors\r\n contributorsToRemove.forEach((userToRemove) => {\r\n if (!newPermissions.projectAdmins.includes(userToRemove)) {\r\n addErrorIfUserIsAssignedToBidPackage(userToRemove);\r\n }\r\n });\r\n }\r\n }\r\n\r\n setErrors(updatedErrors);\r\n },\r\n [errors, projectToEdit?.bidPackages, projectToEdit?.permissions, t],\r\n );\r\n\r\n const validateBidPackages = useCallback(\r\n (bidPackages: ProjectBidPackage[]) => {\r\n // Clear current bid package errors\r\n const updatedErrors = errors.filter((e) => e.id !== bidPackagesErrorId);\r\n\r\n //Check that at least one bid package is selected\r\n if (!bidPackages.find((bp) => bp.isSelected)) {\r\n updatedErrors.push({\r\n id: bidPackagesErrorId,\r\n message: oneBidPackageRequiredError,\r\n });\r\n } else {\r\n // find duplicate selected bid package codes.\r\n const duplicateSelectedBidPackages = bidPackages.filter(\r\n (bp, index, array) =>\r\n bp.isSelected &&\r\n array.findIndex(\r\n (bp2, index2) => bp2.code === bp.code && index2 !== index && bp2.isSelected,\r\n ) !== -1,\r\n );\r\n\r\n // if any duplicates are found, display a validation error describing the offending codes.\r\n if (duplicateSelectedBidPackages.length > 0) {\r\n updatedErrors.push({\r\n id: bidPackagesErrorId,\r\n message: t('project:uniqueBidPackagesRequiredError', {\r\n codes: uniq(duplicateSelectedBidPackages.map((bp) => bp.code)).join(', '),\r\n }),\r\n });\r\n }\r\n }\r\n\r\n setErrors(updatedErrors);\r\n },\r\n [errors, oneBidPackageRequiredError, t],\r\n );\r\n\r\n const updateBidPackages = useCallback(\r\n (updatedBidPackages: ProjectBidPackage[], shouldUpdateContributors: boolean) => {\r\n if (projectToEdit && users) {\r\n // Run validation checks of the bid packages\r\n validateBidPackages(updatedBidPackages);\r\n\r\n const updatedPermissions: ProjectPermissions = {\r\n ...projectToEdit.permissions,\r\n };\r\n\r\n if (shouldUpdateContributors) {\r\n // Get the current contributors\r\n const updatedContributors = [...projectToEdit.permissions.contributors];\r\n const newContributors: string[] = [];\r\n\r\n // Get a unique list of assigned users from the bid packages\r\n const uniqueAssignedUsers = uniq(\r\n updatedBidPackages.map((bp) => bp.assignedToUser).filter((user) => user !== null),\r\n );\r\n\r\n // Add assigned user to contributors if they are not already a contributor or project admin\r\n uniqueAssignedUsers.forEach((u) => {\r\n if (\r\n !updatedContributors.find((uc) => uc === u) &&\r\n !projectToEdit.permissions.projectAdmins.find((up) => up === u)\r\n ) {\r\n const userContributor = users.find((user) => user.email === u);\r\n if (userContributor) {\r\n updatedContributors.push(userContributor.email);\r\n newContributors.push(userContributor.email);\r\n }\r\n }\r\n });\r\n\r\n // This code will fire when the user blurs away from the \"assigned to\" input for a bid package,\r\n // so it will run once for every new contributor we are adding\r\n if (newContributors.length > 0) {\r\n newContributors.forEach((currUser) => {\r\n showInfoNotification(\r\n t('project:contributorsUpdatedTitle'),\r\n t('project:contributorsUpdatedText', {\r\n userName: currUser,\r\n }),\r\n );\r\n });\r\n }\r\n\r\n updatedPermissions.contributors = updatedContributors;\r\n validatePermissions(updatedPermissions);\r\n }\r\n\r\n // Update the edit model\r\n setProjectToEdit({\r\n ...projectToEdit,\r\n bidPackages: updatedBidPackages,\r\n permissions: updatedPermissions,\r\n });\r\n }\r\n },\r\n [projectToEdit, showInfoNotification, t, users, validateBidPackages, validatePermissions],\r\n );\r\n\r\n const updateGeneralRequirements = useCallback(\r\n (updatedGeneralRequirements: ProjectGeneralRequirement[]) => {\r\n if (projectToEdit) {\r\n setProjectToEdit({\r\n ...projectToEdit,\r\n generalRequirements: updatedGeneralRequirements,\r\n });\r\n }\r\n },\r\n [projectToEdit],\r\n );\r\n\r\n const validateFees = useCallback(\r\n (fees: ProjectFee[]) => {\r\n // Clear current fee errors\r\n const updatedErrors = errors.filter((e) => e.id !== feesErrorId);\r\n\r\n // find fees with references that aren't selected.\r\n const feesIncludedButMissingReferencedFee = fees.filter(\r\n (fee, index, array) =>\r\n fee.isSelected &&\r\n fee.feeType === FeeTypes.Percent &&\r\n fee.referenceFeeName &&\r\n !array.find((fee2) => fee2.name === fee.referenceFeeName && fee2.isSelected),\r\n );\r\n\r\n // if any missing references are found, display a validation error describing the offending missing names.\r\n if (feesIncludedButMissingReferencedFee.length > 0) {\r\n updatedErrors.push({\r\n id: feesErrorId,\r\n message: t('project:feeIncludedButMissingReferencedFeeError', {\r\n names: uniq(feesIncludedButMissingReferencedFee.map((fee) => fee.name)).join(', '),\r\n }),\r\n });\r\n } else {\r\n // find duplicate selected fees.\r\n const duplicateSelectedFees = fees.filter(\r\n (fee, index, array) =>\r\n fee.isSelected &&\r\n array.findIndex(\r\n (fee2, index2) => fee2.name === fee.name && index2 !== index && fee2.isSelected,\r\n ) !== -1,\r\n );\r\n\r\n // if any duplicates are found, display a validation error describing the offending names.\r\n if (duplicateSelectedFees.length > 0) {\r\n updatedErrors.push({\r\n id: feesErrorId,\r\n message: t('project:uniqueFeeNamesRequiredError', {\r\n names: uniq(duplicateSelectedFees.map((fee) => fee.name)).join(', '),\r\n }),\r\n });\r\n }\r\n }\r\n\r\n setErrors(updatedErrors);\r\n },\r\n [errors, t],\r\n );\r\n\r\n const updateFees = useCallback(\r\n (updatedFees: ProjectFee[]) => {\r\n if (projectToEdit) {\r\n // Run validation checks of the fees\r\n validateFees(updatedFees);\r\n\r\n setProjectToEdit({\r\n ...projectToEdit,\r\n fees: updatedFees,\r\n });\r\n }\r\n },\r\n [projectToEdit, validateFees],\r\n );\r\n\r\n const validateAlternates = useCallback(\r\n (alternates: ProjectAlternate[]) => {\r\n // Clear current alternate errors\r\n const updatedErrors = errors.filter((e) => e.id !== alternatesErrorId);\r\n\r\n //Check that all alternates are unique\r\n const duplicates = getDuplicates(\r\n alternates.map((alternate) => alternate.name.toLocaleLowerCase().trim()),\r\n );\r\n if (duplicates.length > 0) {\r\n duplicates.forEach((d) => {\r\n updatedErrors.push({\r\n id: alternatesErrorId,\r\n message: duplicateAlternateError,\r\n value: d,\r\n });\r\n });\r\n }\r\n\r\n //Check that no alternates are empty or whitespace\r\n alternates.forEach((a) => {\r\n if (!(a.name || '').length) {\r\n updatedErrors.push({\r\n id: alternatesErrorId,\r\n message: emptyAlternateError,\r\n });\r\n }\r\n });\r\n\r\n setErrors(updatedErrors);\r\n },\r\n [duplicateAlternateError, emptyAlternateError, errors],\r\n );\r\n\r\n const updateAlternates = useCallback(\r\n (alternates: ProjectAlternate[]) => {\r\n if (projectToEdit) {\r\n validateAlternates(alternates);\r\n setProjectToEdit({\r\n ...projectToEdit,\r\n alternates: alternates,\r\n });\r\n }\r\n },\r\n [projectToEdit, validateAlternates],\r\n );\r\n\r\n const updatePermissions = useCallback(\r\n (permissions: ProjectPermissions) => {\r\n if (projectToEdit) {\r\n validatePermissions(permissions);\r\n setProjectToEdit({\r\n ...projectToEdit,\r\n permissions: permissions,\r\n });\r\n }\r\n },\r\n [projectToEdit, validatePermissions],\r\n );\r\n\r\n const processFile = async (info: ProjectInfo): Promise => {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = () => {\r\n try {\r\n resolve(reader.result);\r\n } catch (error) {\r\n reject();\r\n }\r\n };\r\n reader.onerror = () => {\r\n reject();\r\n };\r\n reader.readAsDataURL(info.image!);\r\n });\r\n };\r\n\r\n const saveChanges = async () => {\r\n try {\r\n if (isNew) {\r\n if (projectToEdit) {\r\n setIsProcessing(true);\r\n const info = projectToEdit.information;\r\n\r\n // Convert the selected image into a byte array\r\n let fileData: string | ArrayBuffer | null | undefined;\r\n if (info.image) {\r\n const processedFile = await processFile(info);\r\n if (processedFile) {\r\n //The processedFile is a URI including types, we need to split these off and only include the base64 string\r\n fileData = processedFile.toString().split(',').pop();\r\n }\r\n }\r\n\r\n // Put together the pieces of the CreateProjectCommand\r\n const information: ProjectInformationDTO = {\r\n name: info.name.trim(),\r\n subTitle: info.subtitle.trim(),\r\n siteAddress: {\r\n streetAddress: info.siteAddress.streetAddress?.trim() ?? null,\r\n aptSuiteBldg: info.siteAddress.aptSuiteBldg?.trim() ?? null,\r\n city: info.siteAddress.city?.trim() ?? null,\r\n stateOrRegion: info.siteAddress.stateOrRegion?.trim() ?? null,\r\n country: info.siteAddress.country?.trim() ?? null,\r\n postalCode: info.siteAddress.postalCode?.trim() ?? null,\r\n },\r\n bidDueDate: info.bidDueDate,\r\n startDate: info.startDate,\r\n completionDate: info.completionDate,\r\n owner: info.owner.trim(),\r\n architect: info.architect.trim(),\r\n totalBuildingArea: info.totalBuildingArea.quantity ? info.totalBuildingArea : null,\r\n totalSiteArea: info.totalSiteArea.quantity ? info.totalSiteArea : null,\r\n isHardBid: info.isHardBid,\r\n imageData: fileData as string,\r\n imageName: info.image ? info.image.name : '',\r\n };\r\n const bidPackagesToInclude: string[] = [];\r\n projectToEdit.bidPackages.forEach((bp) => {\r\n if (bp.isSelected) {\r\n bidPackagesToInclude.push(bp.code);\r\n }\r\n });\r\n const bidPackageAssignments: ProjectBidPackageAssignmentDTO[] = [];\r\n projectToEdit.bidPackages.forEach((bp) => {\r\n if (bp.isSelected && bp.assignedToUser !== null) {\r\n bidPackageAssignments.push({\r\n code: bp.code,\r\n assignedUser: bp.assignedToUser,\r\n });\r\n }\r\n });\r\n const generalRequirementsToInclude: string[] = [];\r\n projectToEdit.generalRequirements.forEach((gr) => {\r\n if (gr.isSelected) {\r\n generalRequirementsToInclude.push(gr.description);\r\n }\r\n });\r\n const alternates = projectToEdit.alternates.map((alternate) => alternate.name);\r\n const feesToInclude: string[] = [];\r\n projectToEdit.fees.forEach((fee) => {\r\n if (fee.isSelected && fee.name) {\r\n feesToInclude.push(fee.name);\r\n }\r\n });\r\n const projectAdmins = projectToEdit.permissions.projectAdmins;\r\n const contributors = projectToEdit.permissions.contributors;\r\n\r\n // If the user has manually removed a user as a contributor that is still assigned a bid package\r\n // We want to ensure that user is still included as a contributor for the project\r\n bidPackageAssignments.forEach((bpa) => {\r\n if (bpa.assignedUser !== null && !contributors.find((c) => c === bpa.assignedUser)) {\r\n contributors.push(bpa.assignedUser);\r\n }\r\n });\r\n\r\n const permissions: ProjectPermissionsDTO = {\r\n projectAdmins: projectAdmins,\r\n contributors: contributors,\r\n };\r\n\r\n const commandToProcess = new CreateProjectCommand(\r\n information,\r\n bidPackagesToInclude,\r\n bidPackageAssignments,\r\n generalRequirementsToInclude,\r\n alternates,\r\n feesToInclude,\r\n permissions,\r\n );\r\n\r\n await executeCommand({\r\n commandToExecute: commandToProcess!,\r\n commandExecutionType: 'relies-on-signal-r-for-completion',\r\n commandSuccessCallback: (result: AxiosResponse) => {\r\n if (result) {\r\n newProjectId.current = result.data;\r\n\r\n // If we don't receive a response from signalR in a timely fashion\r\n signalRResponseTimeout.current = setTimeout(() => {\r\n history.push(`${ApplicationRoutes.BID_SUMMARY}/${result.data}`);\r\n }, GeneralConstants.SIGNALR_WAIT_TIMEOUT);\r\n } else {\r\n showErrorNotification(t('general:error'), t('project:createProjectError'));\r\n setIsProcessing(false);\r\n }\r\n },\r\n commandErrorCallback: (error: unknown) => {\r\n // If the create is failing for a business logic reason - we want to display the exact reason to the user\r\n const requestError = error as AxiosError;\r\n if (requestError.response?.status === 422) {\r\n showErrorNotification(\r\n t('general:error'),\r\n t('project:createProjectErrorWithDetail', {\r\n detail: requestError.response?.data?.detail,\r\n }),\r\n );\r\n } else {\r\n showErrorNotification(t('general:error'), t('project:createProjectError'));\r\n }\r\n setIsProcessing(false);\r\n },\r\n });\r\n }\r\n } else {\r\n // If no changes are detected, return early\r\n if (isEqual(project, projectToEdit)) {\r\n showInfoNotification(t('general:noChanges'), t('general:noChangesWereMade'));\r\n return;\r\n }\r\n if (project && projectToEdit) {\r\n setIsProcessing(true);\r\n const info = project.information;\r\n const updatedInfo = projectToEdit.information;\r\n\r\n // handle image upload\r\n let fileData: string | ArrayBuffer | null | undefined;\r\n if (updatedInfo.image) {\r\n const processedFile = await processFile(updatedInfo);\r\n if (processedFile) {\r\n //The processedFile is a URI including types, we need to split these off and only include the base64 string\r\n fileData = processedFile.toString().split(',').pop();\r\n }\r\n }\r\n\r\n // handle image deletion\r\n if (info.imageUri !== '' && updatedInfo.imageUri === '') {\r\n // If there was originally a file, we'll send an empty string for the file data here to indicate a delete\r\n fileData = '';\r\n }\r\n\r\n // Put together siteAddress updates for the ProjectInformationDTO\r\n const previousAddress = info.siteAddress;\r\n const updatedAddress = updatedInfo.siteAddress;\r\n const siteAddressUpdates: Address = {\r\n streetAddress: isEqual(previousAddress.streetAddress, updatedAddress.streetAddress)\r\n ? null\r\n : updatedAddress.streetAddress?.trim() ?? null,\r\n aptSuiteBldg: isEqual(previousAddress.aptSuiteBldg, updatedAddress.aptSuiteBldg)\r\n ? null\r\n : updatedAddress.aptSuiteBldg?.trim() ?? null,\r\n city: isEqual(previousAddress.city, updatedAddress.city)\r\n ? null\r\n : updatedAddress.city?.trim() ?? null,\r\n stateOrRegion: isEqual(previousAddress.stateOrRegion, updatedAddress.stateOrRegion)\r\n ? null\r\n : updatedAddress.stateOrRegion?.trim() ?? null,\r\n postalCode: isEqual(previousAddress.postalCode, updatedAddress.postalCode)\r\n ? null\r\n : updatedAddress.postalCode?.trim() ?? null,\r\n country: isEqual(previousAddress.country, updatedAddress.country)\r\n ? null\r\n : updatedAddress.country?.trim() ?? null,\r\n };\r\n\r\n // Put together the pieces of the UpdateProjectCommand\r\n const information: ProjectInformationDTO = {\r\n name: isEqual(info.name, updatedInfo.name) ? null : updatedInfo.name.trim(),\r\n subTitle: isEqual(info.subtitle, updatedInfo.subtitle)\r\n ? null\r\n : updatedInfo.subtitle.trim(),\r\n siteAddress: isEqual(info.siteAddress, updatedInfo.siteAddress)\r\n ? null\r\n : siteAddressUpdates,\r\n bidDueDate: isEqual(info.bidDueDate, updatedInfo.bidDueDate)\r\n ? null\r\n : updatedInfo.bidDueDate,\r\n startDate: updatedInfo.startDate,\r\n completionDate: updatedInfo.completionDate,\r\n owner: isEqual(info.owner, updatedInfo.owner) ? null : updatedInfo.owner.trim(),\r\n architect: isEqual(info.architect, updatedInfo.architect)\r\n ? null\r\n : updatedInfo.architect.trim(),\r\n totalBuildingArea: isEqual(info.totalBuildingArea, updatedInfo.totalBuildingArea)\r\n ? null\r\n : updatedInfo.totalBuildingArea,\r\n totalSiteArea: isEqual(info.totalSiteArea, updatedInfo.totalSiteArea)\r\n ? null\r\n : updatedInfo.totalSiteArea,\r\n isHardBid: isEqual(info.isHardBid, updatedInfo.isHardBid)\r\n ? null\r\n : updatedInfo.isHardBid,\r\n imageData: fileData as string,\r\n imageName: updatedInfo.image ? updatedInfo.image.name : '',\r\n };\r\n\r\n // Bid Package updates\r\n const bidPackagesToInclude: string[] = [];\r\n const bidPackagesToExclude: string[] = [];\r\n const bidPackageAssignments: ProjectBidPackageAssignmentDTO[] = [];\r\n if (\r\n project.bidPackages &&\r\n projectToEdit.bidPackages &&\r\n !isEqual(project.bidPackages, projectToEdit.bidPackages)\r\n ) {\r\n projectToEdit.bidPackages.forEach((curr) => {\r\n const previousBidPackage = project.bidPackages.find((prev) => prev.id === curr.id);\r\n // If the bid package was previously unchecked and is now checked, add to inclusions\r\n if (previousBidPackage && !previousBidPackage.isSelected && curr.isSelected) {\r\n bidPackagesToInclude.push(curr.code);\r\n }\r\n // If the bid package was previously checked and is now unchecked, add to exclusions\r\n if (previousBidPackage && previousBidPackage.isSelected && !curr.isSelected) {\r\n bidPackagesToExclude.push(curr.code);\r\n }\r\n // If the bid package assignment is different that the previous assignment, update the value\r\n if (previousBidPackage?.assignedToUser !== curr.assignedToUser) {\r\n bidPackageAssignments.push({\r\n code: curr.code,\r\n assignedUser: curr.assignedToUser ? curr.assignedToUser : null,\r\n });\r\n }\r\n });\r\n }\r\n\r\n // General Requirement updates\r\n const generalRequirementsToInclude: string[] = [];\r\n const generalRequirementsToExclude: string[] = [];\r\n if (\r\n project.generalRequirements &&\r\n projectToEdit.generalRequirements &&\r\n (!isEqual(project.generalRequirements, projectToEdit.generalRequirements) ||\r\n bidPackagesToInclude.length > 0)\r\n ) {\r\n projectToEdit.generalRequirements.forEach((curr) => {\r\n if (curr.isSelected) {\r\n generalRequirementsToInclude.push(curr.description);\r\n } else {\r\n generalRequirementsToExclude.push(curr.description);\r\n }\r\n });\r\n }\r\n\r\n // Alternates updates\r\n let alternatesToUpdate: ProjectAlternateUpdateDTO[] = [];\r\n let alternatesToAdd: string[] = [];\r\n let alternatesToDelete: string[] = [];\r\n if (\r\n project.alternates &&\r\n projectToEdit.alternates &&\r\n !isEqual(project.alternates, projectToEdit.alternates)\r\n ) {\r\n // Alternates that exist on the updated and original collections with the same id but with different names\r\n alternatesToUpdate = projectToEdit.alternates\r\n .filter((updatedProjectAlternate) =>\r\n project.alternates.find(\r\n (originalAlternate) =>\r\n updatedProjectAlternate.id === originalAlternate.id &&\r\n updatedProjectAlternate.name !== originalAlternate.name,\r\n ),\r\n )\r\n .map((alternateWithUpdate) => {\r\n const alternateToUpdate = project.alternates.find(\r\n (originalAlternate) => alternateWithUpdate.id === originalAlternate.id,\r\n );\r\n\r\n return {\r\n alternateName: alternateToUpdate!.name,\r\n updatedAlternateName: alternateWithUpdate.name,\r\n };\r\n });\r\n\r\n alternatesToAdd = projectToEdit.alternates\r\n .filter(\r\n (alternate) =>\r\n // Include alternates that don't appear in the original collection and aren't an original alternate being updated\r\n (!project.alternates.find(\r\n (originalAlternate) => originalAlternate.name === alternate.name,\r\n ) &&\r\n !alternatesToUpdate.find(\r\n (updatedAlternate) =>\r\n updatedAlternate.updatedAlternateName === alternate.name,\r\n )) ||\r\n // Include alternates that were part of the original collection and are now being added at the same time the previous alternate of this name is being updated\r\n (project.alternates.find(\r\n (originalAlternate) => originalAlternate.name === alternate.name,\r\n ) &&\r\n alternatesToUpdate.find(\r\n (updatedAlternate) => updatedAlternate.alternateName === alternate.name,\r\n )),\r\n )\r\n .map((alternate) => alternate.name);\r\n\r\n // Alternates that don't exist on the updated collection that were on the original collection\r\n alternatesToDelete = project.alternates\r\n .filter(\r\n (alternate) =>\r\n !projectToEdit.alternates.find(\r\n (updatedAlternate) => updatedAlternate.name === alternate.name,\r\n ) &&\r\n !alternatesToUpdate.find(\r\n (updatedAlternate) => updatedAlternate.alternateName === alternate.name,\r\n ),\r\n )\r\n .map((alternate) => alternate.name);\r\n }\r\n\r\n // Fee updates\r\n const feesToInclude: string[] = [];\r\n const feesToExclude: string[] = [];\r\n if (project.fees && projectToEdit.fees && !isEqual(project.fees, projectToEdit.fees)) {\r\n projectToEdit.fees.forEach((curr) => {\r\n const previousFee = project.fees.find((prev) => prev.id === curr.id);\r\n // If the fee was previously unchecked and is now checked, add to inclusions\r\n if (previousFee && !previousFee.isSelected && curr.isSelected && curr.name) {\r\n feesToInclude.push(curr.name);\r\n }\r\n // If the fee was previously checked and is now unchecked, add to exclusions\r\n if (previousFee && previousFee.isSelected && !curr.isSelected && curr.name) {\r\n feesToExclude.push(curr.name);\r\n }\r\n });\r\n }\r\n\r\n // Permissions updates\r\n const permissions: ProjectPermissionsDTO = {\r\n projectAdmins: projectToEdit.permissions.projectAdmins,\r\n contributors: projectToEdit.permissions.contributors,\r\n };\r\n\r\n const commandToProcess = new UpdateProjectCommand(\r\n projectId,\r\n information,\r\n bidPackagesToInclude,\r\n bidPackagesToExclude,\r\n bidPackageAssignments,\r\n generalRequirementsToInclude,\r\n generalRequirementsToExclude,\r\n alternatesToUpdate.map((a) => ({\r\n alternateName: a.alternateName,\r\n updatedAlternateName: a.updatedAlternateName.trim(),\r\n })),\r\n alternatesToAdd.map((a) => a.trim()),\r\n alternatesToDelete,\r\n feesToInclude,\r\n feesToExclude,\r\n permissions,\r\n );\r\n\r\n // Execute Command\r\n await executeCommand({\r\n commandToExecute: commandToProcess!,\r\n commandExecutionType: 'relies-on-signal-r-for-completion',\r\n commandSuccessCallback: () => {\r\n // NOTE: We do not do anything here -- the signalR event should redirect the user, and if it never comes,\r\n // the loading overlay will eventually turn off and we will call the timeout function below to redirect the user\r\n },\r\n commandErrorCallback: (error: unknown) => {\r\n // If the update is failing for a business logic reason - we want to display the exact reason to the user\r\n const requestError = error as AxiosError;\r\n if (requestError.response?.status === 422) {\r\n showErrorNotification(\r\n t('general:error'),\r\n t('project:updateProjectErrorWithDetail', {\r\n detail: requestError.response?.data?.detail,\r\n }),\r\n );\r\n } else {\r\n showErrorNotification(t('general:error'), t('project:updateProjectError'));\r\n }\r\n setIsProcessing(false);\r\n },\r\n commandTimeoutFunction: () => {\r\n navigateBack(history);\r\n return Promise.resolve();\r\n },\r\n });\r\n }\r\n }\r\n } catch (error) {\r\n logger.logError(error);\r\n showErrorNotification(\r\n t('general:error'),\r\n isNew ? t('project:createProjectError') : t('project:updateProjectError'),\r\n );\r\n }\r\n };\r\n\r\n const onSaveClick = async () => {\r\n // Run validation checks in case the user skipped required inputs\r\n if (projectToEdit && validateProjectInformation(projectToEdit.information)) {\r\n saveChanges();\r\n } else {\r\n // After a short pause, scroll the user back up to the project information section to address validation errors\r\n setTimeout(() => {\r\n scrollToRef(projectInformationRef);\r\n }, 500);\r\n }\r\n };\r\n\r\n const navigateAway = (): void => {\r\n if (isNew) {\r\n // If this is a new project, navigate back home\r\n history.push(ApplicationRoutes.HOME);\r\n } else {\r\n // If this is an edited project, navigate to the previous page or home\r\n navigateBack(history);\r\n }\r\n };\r\n\r\n const onDiscardClick = (): void => {\r\n if (projectToEdit !== project || errors.length > 0) {\r\n showConfirmationOverlay({\r\n text: t('general:discardConfirmation'),\r\n buttons: [\r\n {\r\n text: t('general:discard'),\r\n onClick: (): void => {\r\n navigateAway();\r\n hideConfirmationOverlay();\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:cancel'),\r\n onClick: (): void => {\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n } else {\r\n navigateAway();\r\n }\r\n };\r\n\r\n const getFrozenEntitiesNames = (): string[] => {\r\n let returnValue: string[] = [];\r\n\r\n // If we have bid packages that are frozen, show the user the bid package name\r\n if (bidPackageIdsThatAreFrozen.length > 0) {\r\n bidPackageIdsThatAreFrozen.forEach((v) => {\r\n const matchingBidPackage = projectToEdit?.bidPackages.find((m) => m.id === v);\r\n\r\n if (matchingBidPackage) {\r\n returnValue.push(\r\n `${t('general:bidPackage')} - ${matchingBidPackage.code} - ${\r\n matchingBidPackage.description\r\n }`,\r\n );\r\n }\r\n });\r\n }\r\n\r\n if (projectUploadContainerIdIsFrozen) {\r\n returnValue.push(t('general:projectImage'));\r\n }\r\n\r\n returnValue = sortBy(returnValue, (v) => v);\r\n\r\n return returnValue;\r\n };\r\n\r\n const frozenEntitiesNameStrings = getFrozenEntitiesNames();\r\n\r\n return (\r\n <>\r\n
    \r\n {frozenEntitiesNameStrings.length > 0 ? (\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n \r\n
    \r\n {projectToEdit && users && isLoaded ? (\r\n <>\r\n
    \r\n
    \r\n {\r\n \r\n }\r\n
    \r\n
    \r\n
    \r\n {\r\n setIsBidPackagesAreaOpen(!isBidPackagesAreaOpen);\r\n }}\r\n >\r\n

    \r\n \r\n \r\n \r\n \r\n {t('project:includedBidPackages')}\r\n \r\n

    \r\n
    \r\n \r\n
    \r\n {\r\n \r\n }\r\n
    \r\n
    \r\n
    \r\n {projectToEdit.generalRequirements ? (\r\n
    \r\n {\r\n setIsGeneralRequirementsAreaOpen(!isGeneralRequirementsAreaOpen);\r\n }}\r\n >\r\n

    \r\n \r\n \r\n \r\n\r\n \r\n {t('project:generalRequirements')}\r\n \r\n

    \r\n
    \r\n \r\n
    \r\n \r\n\r\n {!projectToEdit.generalRequirements.length ? (\r\n \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n
    \r\n \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n {\r\n setIsAlternatesAreaOpen(!isAlternatesAreaOpen);\r\n }}\r\n >\r\n

    \r\n \r\n \r\n \r\n \r\n {t('project:alternates')}\r\n \r\n

    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n \r\n {projectToEdit.fees.length > 0 ? (\r\n
    \r\n {\r\n setIsFeesAreaOpen(!isFeesAreaOpen);\r\n }}\r\n >\r\n

    \r\n \r\n \r\n \r\n \r\n {t('project:fees')}\r\n \r\n

    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n \r\n ) : (\r\n <>\r\n )}\r\n
    \r\n {\r\n setIsPermissionsAreaOpen(!isPermissionsAreaOpen);\r\n }}\r\n >\r\n

    \r\n \r\n \r\n \r\n \r\n {t('project:permissions')}\r\n \r\n

    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n \r\n\r\n
    \r\n
    \r\n
    \r\n \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n ) : (\r\n <>\r\n )}\r\n \r\n \r\n );\r\n};\r\n\r\nexport default ProjectPage;\r\n","export interface Import {\r\n name: string;\r\n translations: Dictionary;\r\n}\r\n\r\nconst getFileNameWithoutExtension = (fileName: string): string => {\r\n return fileName\r\n .slice(2) // remove starting ./\r\n .replace(/\\.[^/.]+$/, ''); // remove file extension\r\n};\r\n\r\n// NOTE: webpack defines a global context rather than a module so we must fully qualify the type\r\nconst importAll = (requireContext: __WebpackModuleApi.RequireContext): Import[] => {\r\n return requireContext.keys().map(\r\n (fileName): Import => ({\r\n name: getFileNameWithoutExtension(fileName),\r\n translations: requireContext(fileName),\r\n }),\r\n );\r\n};\r\n\r\nexport { importAll };\r\n","import i18n from 'i18next';\nimport moment from 'moment';\nimport { Import, importAll } from '../utils/imports';\n\nexport const DEFAULT_LANG = 'en-US';\n\nexport const TranslationFilesMap: Dictionary<() => Import[]> = {\n 'en-US': () => importAll(require.context('./translations/en-US', false, /\\.json$/i)),\n 'fr-CA': () => importAll(require.context('./translations/fr-CA', false, /\\.json$/i)),\n};\n\nexport const loadTranslationsForLocale = (locale: string): void => {\n const getTranslationsFunc = TranslationFilesMap[locale] as () => Import[];\n\n if (!getTranslationsFunc) {\n throw new Error(\n `Could not find translations for locale \"${locale}\". Verify that they are added to \"translationFilesMap\" in \"i18n.ts\"`,\n );\n }\n\n const translationFiles = getTranslationsFunc();\n\n translationFiles.forEach((translationFile) => {\n i18n.addResourceBundle(locale, translationFile.name, translationFile.translations);\n });\n};\n\n// NOTE: This function declaration is defined by i18n so we must abide by their types\nexport const format = (value: unknown, format?: string, lng?: string): string => {\n if (value instanceof Date) {\n if (!lng) {\n throw new Error('`lng` must have a value for date formatting');\n }\n\n const date = moment(value).locale(lng);\n\n if (format === 'shortDate') {\n return date.format('L');\n } else if (format === 'longDate') {\n return date.format('LL');\n }\n\n return date.toString();\n }\n\n if (typeof value === 'number') {\n const num = value as number;\n\n if (format === 'numberFormat') {\n return num.toLocaleString(lng);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (value as any).toString();\n};\n","import axios from 'axios';\r\nimport { useContext, useEffect } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { ConfirmationOverlayContext } from '../../app/common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport { BTGeneralContext } from '../../app/common-page-components/general-contexts/BTGeneralContext';\r\nimport { NotificationPanelContext } from '../../app/common-page-components/notification-panel/NotificationPanelContext';\r\nimport { useLogger } from '../../services/logger/Logger';\r\nimport { isEnvironment } from '../general';\r\n\r\nexport const LOCAL_STORAGE_KEY_UPDATED_TO_NEW_VERSION = 'UserUpdatedToNewVersion';\r\n\r\nconst INTERVAL_VERSION_CHECK = 10 * 60 * 1000; // Every 10 minutes\r\n\r\nconst CURRENT_APPLICATION_HASH = '{{APPLICATION_HASH}}';\r\n\r\n// The version check logic in Bid Day works as follows:\r\n//\r\n// When the application is built, a unique hash is automatically added to the file names of the minified JavaScript.\r\n// A NodeJS script is then run and does 2 things:\r\n// 1) It retrieves that unique hash from the file names and replaces the \"{{APPLICATION_HASH}}\" string in the outputted,\r\n// minified JavaScript (from this file) with that hash. This code will then have access to that hash value at runtime.\r\n// 2) That same hash value is written to a file named \"version.json\" in the build output directory and that file will\r\n// be deployed alongside the website code to the web server.\r\n//\r\n// In this code, we periodically make an AJAX call to the web server for that \"version.json\" file and compare the resulting hash\r\n// value in that file with our local hash value. If they do not match, it means we are running old code.\r\n// If we are running old code, we notify the user a new version is available and programatically refresh the page, which should\r\n// force the browser to make a fresh request to the web server and not use cached content.\r\n//\r\n// This process was adapted from the following blog, but is a well documented practice that can be found elsewhere.\r\n// https://blog.nodeswat.com/automagic-reload-for-clients-after-deploy-with-angular-4-8440c9fdd96c\r\n\r\nconst useVersionCheck = (): void => {\r\n const logger = useLogger();\r\n\r\n const { showConfirmationOverlay, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n\r\n const { showSuccessNotification } = useContext(NotificationPanelContext);\r\n\r\n const { onUserJustGotTheLatestUpdate, onAppWillRestart } = useContext(BTGeneralContext);\r\n\r\n const { t } = useTranslation();\r\n\r\n useEffect(() => {\r\n if (isEnvironment('local')) {\r\n return;\r\n }\r\n\r\n let versionCheckTimeout: NodeJS.Timeout | null = null;\r\n\r\n const checkVersion = async () => {\r\n let newVersionIsAvailable = false;\r\n\r\n try {\r\n // NOTE: We append a timestamp to bust some standard web caching\r\n const versionData: { version: string; hash: string } = (\r\n await axios.get(`/version.json?t=${new Date().getTime()}`)\r\n ).data;\r\n\r\n if (!versionData.hash) {\r\n throw new Error('Application hash not found on the server.');\r\n }\r\n\r\n newVersionIsAvailable = versionData.hash !== CURRENT_APPLICATION_HASH;\r\n\r\n if (newVersionIsAvailable) {\r\n // Reload the application if something new and shiny is available.\r\n // Doing it programatically like this will cause the browser to make a fresh request to the server\r\n // for the new static website files.\r\n showConfirmationOverlay({\r\n text: t('general:newVersionAvailable'),\r\n text2: t('general:newVersionAvailable2'),\r\n image: 'bid-day-logo',\r\n allowEscapeKey: false,\r\n buttons: [\r\n {\r\n text: t('general:getLatestVersion'),\r\n onClick: (): void => {\r\n // Set a local storage value, so when the app reloads, it knows the user just updated and shows them a message\r\n // that they're running the latest version of Bid Day (this happens below)\r\n localStorage.setItem(\r\n LOCAL_STORAGE_KEY_UPDATED_TO_NEW_VERSION,\r\n JSON.stringify(true),\r\n );\r\n\r\n document.location.reload();\r\n },\r\n color: 'normal',\r\n },\r\n {\r\n text: t('general:getLatestVersionLater'),\r\n onClick: (): void => {\r\n onAppWillRestart();\r\n\r\n hideConfirmationOverlay();\r\n },\r\n color: 'gray',\r\n },\r\n ],\r\n });\r\n } else {\r\n const didUserGetNewestVersionAfterBeingPrompted = localStorage.getItem(\r\n LOCAL_STORAGE_KEY_UPDATED_TO_NEW_VERSION,\r\n );\r\n\r\n if (\r\n didUserGetNewestVersionAfterBeingPrompted &&\r\n JSON.parse(didUserGetNewestVersionAfterBeingPrompted) === true\r\n ) {\r\n localStorage.removeItem(LOCAL_STORAGE_KEY_UPDATED_TO_NEW_VERSION);\r\n\r\n showSuccessNotification(t('general:upToDate'), t('general:upToDateMessage'));\r\n\r\n // Trigger the observable that lets other code know, so we can show a little celebration\r\n onUserJustGotTheLatestUpdate();\r\n }\r\n\r\n versionCheckTimeout = setTimeout(() => {\r\n checkVersion();\r\n }, INTERVAL_VERSION_CHECK);\r\n }\r\n } catch (errorObj) {\r\n logger.logError(errorObj);\r\n logger.logError('Could not get the Bid Day version file.');\r\n\r\n // If something failed, try try again\r\n versionCheckTimeout = setTimeout(() => {\r\n checkVersion();\r\n }, INTERVAL_VERSION_CHECK);\r\n }\r\n };\r\n\r\n // Run the version check shortly after the app loads, in case the app was loaded via cached or out of date files\r\n versionCheckTimeout = setTimeout(() => {\r\n checkVersion();\r\n }, 2000);\r\n\r\n return () => {\r\n if (versionCheckTimeout) {\r\n clearTimeout(versionCheckTimeout);\r\n }\r\n };\r\n }, [\r\n hideConfirmationOverlay,\r\n logger,\r\n onAppWillRestart,\r\n onUserJustGotTheLatestUpdate,\r\n showConfirmationOverlay,\r\n showSuccessNotification,\r\n t,\r\n ]);\r\n};\r\n\r\nexport default useVersionCheck;\r\n","import { useEffect, useRef } from 'react';\r\n\r\ninterface ReturnValue {\r\n addScriptToPage: (url: string) => void;\r\n}\r\n\r\nconst useScript = (): ReturnValue => {\r\n const scriptElement = useRef();\r\n\r\n const addScriptToPage = (url: string) => {\r\n if (!url) {\r\n return;\r\n }\r\n\r\n const script = document.createElement('script');\r\n script.src = url;\r\n script.async = true;\r\n\r\n document.body.appendChild(script);\r\n\r\n scriptElement.current = script;\r\n };\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (scriptElement.current) {\r\n document.body.removeChild(scriptElement.current);\r\n }\r\n };\r\n }, []);\r\n\r\n return {\r\n addScriptToPage,\r\n };\r\n};\r\n\r\nexport default useScript;\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { useCallback, useEffect } from 'react';\r\nimport { getConfig } from '../config';\r\nimport useScript from './useScript';\r\n\r\nconst walkMeScriptUrl = getConfig('REACT_APP_WALKME_SCRIPT') as string;\r\nconst walkMeUserInfoVariableName = 'walkMeUserInfo';\r\n\r\ninterface SetWalkMeUserInfoParameter {\r\n userIdentifier: string | null;\r\n isAdmin: boolean;\r\n isProjectAdmin: boolean;\r\n isContributor: boolean;\r\n}\r\n\r\ninterface UseWalkMeReturnValue {\r\n setWalkMeUserInfo: (data: SetWalkMeUserInfoParameter | null) => void;\r\n}\r\n\r\nconst useWalkMe = (): UseWalkMeReturnValue => {\r\n // NOTE: The WalkMe script URL is only applicable for certain environments and will have a value of '0'\r\n // when the environment is one it doesn't pertain to.\r\n // NOTE: To debug WalkMe content locally, add the WalkMe URL from the code snippet for \"local development\"\r\n // (in the WalkMe editor, go to the hamburger menu and choose \"Snippet\") into the \".env\" file.\r\n const walkMeScriptUrlToUse = walkMeScriptUrl === '0' ? '' : walkMeScriptUrl;\r\n\r\n const { addScriptToPage } = useScript();\r\n\r\n const initializeWalkMeScript = useCallback(() => {\r\n // Required by WalkMe\r\n (window as any)._walkmeConfig = { smartLoad: true };\r\n\r\n // Create an object that will hold all of our user information\r\n (window as any)[walkMeUserInfoVariableName] = {};\r\n }, []);\r\n\r\n const setWalkMeUserInfo = useCallback(\r\n (data: SetWalkMeUserInfoParameter | null): void => {\r\n // Do nothing if we aren't configuring WalkMe.\r\n // NOTE: Comment out this code when debugging WalkMe content locally, otherwise it won't find\r\n // the user info it needs.\r\n if (!walkMeScriptUrlToUse) {\r\n return;\r\n }\r\n\r\n if (data) {\r\n // Add the WalkMe script to the page\r\n addScriptToPage(walkMeScriptUrl);\r\n\r\n initializeWalkMeScript();\r\n\r\n (window as any)[walkMeUserInfoVariableName] = {\r\n identifier: data.userIdentifier,\r\n isAdmin: data.isAdmin,\r\n isProjectAdmin: data.isProjectAdmin,\r\n isContributor: data.isContributor,\r\n };\r\n } else {\r\n // Reset the user info object\r\n if ((window as any)[walkMeUserInfoVariableName] !== undefined) {\r\n (window as any)[walkMeUserInfoVariableName] = {};\r\n }\r\n }\r\n },\r\n [addScriptToPage, initializeWalkMeScript, walkMeScriptUrlToUse],\r\n );\r\n\r\n useEffect(() => {\r\n // Do nothing if we aren't configuring WalkMe\r\n if (!walkMeScriptUrlToUse) {\r\n return;\r\n }\r\n }, [walkMeScriptUrlToUse]);\r\n\r\n return {\r\n setWalkMeUserInfo,\r\n };\r\n};\r\n\r\nexport default useWalkMe;\r\n","import { IntlProvider } from '@progress/kendo-react-intl';\r\nimport Big from 'big.js';\r\nimport i18n from 'i18next';\r\nimport * as logLevelLog from 'loglevel';\r\nimport * as moment from 'moment';\r\nimport React, {\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useLayoutEffect,\r\n useRef,\r\n useState,\r\n} from 'react';\r\nimport { useBeforeunload } from 'react-beforeunload';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Redirect, Route, Switch } from 'react-router';\r\nimport { useHistory, useLocation } from 'react-router-dom';\r\nimport {\r\n BTGeneralContext,\r\n WindowDimensions,\r\n} from './app/common-page-components/general-contexts/BTGeneralContext';\r\nimport { BTDropDownListOption } from './app/common-page-components/inputs/BTDropDownList';\r\nimport Layout from './app/common-page-components/layout/Layout';\r\nimport { LoadingPageOverlayContext } from './app/common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport { NotificationPanelContext } from './app/common-page-components/notification-panel/NotificationPanelContext';\r\nimport AuthenticatedRoute from './app/common-page-components/routes/AuthenticatedRoute';\r\nimport ProjectGuard from './app/common-page-components/routes/guards/ProjectGuard';\r\nimport { SupportOverlayContext } from './app/common-page-components/support-overlay/SupportOverlayContext';\r\nimport FrozenEntitiesAdminPage from './app/pages/admin/frozen-entities/FrozenEntitiesAdminPage';\r\nimport GenericErrorPage from './app/pages/common/error/generic-error/GenericErrorPage';\r\nimport PageNotFoundPage from './app/pages/common/error/page-not-found/PageNotFoundPage';\r\nimport UnauthorizedPage from './app/pages/common/error/unauthorized/UnauthorizedPage';\r\nimport UnlicensedPage from './app/pages/common/error/unlicensed/UnlicensedPage';\r\nimport HomePage from './app/pages/common/home/HomePage';\r\nimport LoginPage from './app/pages/common/login/LoginPage';\r\nimport BidPackageMaintenancePage from './app/pages/settings/bid-packages/BidPackageMaintenancePage';\r\nimport FeesPage from './app/pages/settings/fees/FeesPage';\r\nimport GeneralConditionsPage from './app/pages/settings/general-conditions/GeneralConditionsPage';\r\nimport GeneralRequirementsPage from './app/pages/settings/general-requirements/GeneralRequirementsPage';\r\nimport PreferencesPage from './app/pages/settings/preferences/PreferencesPage';\r\nimport UnitsOfMeasurePage from './app/pages/settings/units-of-measure/UnitsOfMeasurePage';\r\nimport UserPermissionsPage from './app/pages/settings/user-permissions/UserPermissionsPage';\r\nimport BidPackagePage from './app/pages/specific/bid-package/BidPackagePage';\r\nimport BidSummaryPage from './app/pages/specific/bid-summary/BidSummaryPage';\r\nimport ProjectPage from './app/pages/specific/project/ProjectPage';\r\nimport ApplicationRoutes from './constants/routes';\r\nimport AdminRoutes from './constants/routes/admin-routes';\r\nimport SystemValues from './constants/system-values';\r\nimport { UserRolesValues } from './constants/users/user-roles';\r\nimport { DEFAULT_LANG } from './internationalization/i18n';\r\nimport { LoginApi, SystemValuesApi } from './services';\r\nimport {\r\n AuthenticationService,\r\n SSOErrorCode,\r\n SSOPasswordResetStatus,\r\n} from './services/authentication/authentication-service';\r\nimport { NotificationService } from './services/notification/notification-service';\r\nimport './styles/kendo/all.css';\r\nimport './styles/kendo/variables.scss';\r\nimport './styles/walkme/walkme.scss';\r\nimport { initializeFontAwesomeIcons } from './utils/font-awesome';\r\nimport { getEnvironmentName } from './utils/general';\r\nimport useVersionCheck from './utils/hooks/useVersionCheck';\r\nimport useWalkMe from './utils/hooks/useWalkMe';\r\n\r\n// Set global log on window. We do this so that it is available from the browser's console\r\n// to enable more detailed logging on a deployed site\r\n//\r\n// NOTE: This should not be used directly in our components. We wrap it with the useLogger hook, so use that\r\nwindow.log = logLevelLog;\r\n\r\n// Set the configuration for Big.JS\r\nBig.RM = 0; // Rounding disabled to prevent incorrect display of data as we already handle rounding in our formatting functions (ie: FormatNumberAsCurrency())\r\n\r\ninitializeFontAwesomeIcons();\r\n\r\nconst OVERRIDE_SUPPORT_OVERLAY = 'OverrideSupportOverlay';\r\nconst TARGET_CLIENT_ORG_ID = 'TargetClientOrgId';\r\n\r\nconst App: React.FC = () => {\r\n const [locale, setLocale] = useState(DEFAULT_LANG);\r\n\r\n // Configure WalkMe\r\n const { setWalkMeUserInfo } = useWalkMe();\r\n\r\n // Configure the version check service\r\n useVersionCheck();\r\n\r\n const onLanguageChanged = useCallback((lang: string) => {\r\n moment.locale(lang); // Update moment locale globally\r\n setLocale(lang); // Update locale state for kendo provider\r\n }, []);\r\n\r\n const history = useHistory();\r\n const location = useLocation();\r\n const { t } = useTranslation();\r\n\r\n i18n.on('languageChanged', onLanguageChanged);\r\n\r\n const lastLocationValue = useRef('');\r\n const lastValue_ScrollX = useRef(0);\r\n const lastValue_ScrollY = useRef(0);\r\n const lastValue_WindowSize = useRef({\r\n height: 0,\r\n width: 0,\r\n });\r\n\r\n const { showSuccessNotification, showErrorNotification } = useContext(NotificationPanelContext);\r\n const { showPageLoadingOverlay, hidePageLoadingOverlay } = useContext(LoadingPageOverlayContext);\r\n const { showSupportOverlay, hideSupportOverlay } = useContext(SupportOverlayContext);\r\n\r\n const { setPageScroll_X, setPageScroll_Y, setSystemSettings, setWindowResize } = useContext(\r\n BTGeneralContext,\r\n );\r\n\r\n const [allInitialDataIsLoaded, setAllInitialDataIsLoaded] = useState(false);\r\n const [shouldRedirectUnlicensedUser, setShouldRedirectUnlicensedUser] = useState(false);\r\n\r\n // Set tab title\r\n useEffect(() => {\r\n const envName = getEnvironmentName().toUpperCase();\r\n document.title = envName.includes('PROD') ? 'DESTINI Bid Day' : `DESTINI Bid Day - ${envName}`;\r\n }, []);\r\n\r\n // Initial data load\r\n useEffect(() => {\r\n const handleSSOErrors = (): boolean => {\r\n const ssoError = AuthenticationService.getLastError();\r\n if (ssoError) {\r\n AuthenticationService.clearLastError(); // clear the error so we don't show it again\r\n showErrorNotification(t('general:error'), ssoError.message);\r\n\r\n switch (ssoError.code) {\r\n case SSOErrorCode.OtherError:\r\n history.push(ApplicationRoutes.ERROR_ERROR);\r\n break;\r\n case SSOErrorCode.LicensingAppSSOError:\r\n history.push(ApplicationRoutes.ERROR_UNAUTHORIZED);\r\n break;\r\n }\r\n return true;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n // When the user initiates a password reset flow, they get redirected to an SSO page, then back to our app with query string parameters.\r\n // The MSAL callback will be invoked, which will handle the code passed in the query string and redirect to the password reset\r\n // Once the user has reset their password, they will be redirected back to our app, where we need to indicate success\r\n const handleSSOPasswordResetLogic = (): boolean => {\r\n const ssoPasswordResetStatus = AuthenticationService.getPasswordResetStatus();\r\n\r\n if (ssoPasswordResetStatus === SSOPasswordResetStatus.Initiated) {\r\n return false;\r\n }\r\n\r\n // If there was a successful password reset, tell the user\r\n if (ssoPasswordResetStatus === SSOPasswordResetStatus.Completed) {\r\n showSuccessNotification(\r\n t('general:success'),\r\n 'Your password was changed successfully. Please log in using your new credentials.',\r\n );\r\n }\r\n\r\n return true;\r\n };\r\n\r\n // Returns true if we should render the app\r\n const checkUserAuthenticationStatus = async (): Promise => {\r\n // Since this can fire several times because of its dependencies, we only want to take action when the location changes\r\n if (lastLocationValue.current === location.pathname) {\r\n return false;\r\n }\r\n\r\n AuthenticationService.init(t('general:error_Generic'));\r\n\r\n // If the URL contains a hash for the SSO service, MSAL will handle it and redirect\r\n // don't render the app at this point\r\n if (AuthenticationService.urlContainsSSOHash(location.hash)) {\r\n return false;\r\n }\r\n\r\n // Don't render the app if there are SSO errors\r\n if (handleSSOErrors()) {\r\n return false;\r\n }\r\n\r\n // Don't render the app if a password reset is in progress\r\n if (!handleSSOPasswordResetLogic()) {\r\n return false;\r\n }\r\n\r\n // Render the app if the user is not authenticated (so they can login)\r\n if (!AuthenticationService.userIsAuthenticated()) {\r\n return true;\r\n }\r\n\r\n // If the user is already logged in, render the app without the login process\r\n if (AuthenticationService.userIsLoggedIn()) {\r\n return true;\r\n } else {\r\n // reset the flag so we don't render any page routes until the user is logged in\r\n lastLocationValue.current = location.pathname;\r\n showPageLoadingOverlay();\r\n if (!localStorage.getItem(OVERRIDE_SUPPORT_OVERLAY)) {\r\n // This initial login is required to set the BidDaySupport role in the application\r\n try {\r\n const showBidDaySupportClientSelector = await AuthenticationService.login(\r\n t('general:unableToAuthenticate'),\r\n t('general:unableToLogin'),\r\n );\r\n\r\n // If the user is a Bid Day Support user, prompt them with client options before login\r\n if (showBidDaySupportClientSelector) {\r\n const loadClientsAndShowOverlay = async () => {\r\n const clientOrganizations = await LoginApi.getClientOrganizations();\r\n const options: BTDropDownListOption[] = clientOrganizations.map(\r\n (client: ClientOrganization) => {\r\n return { value: client.id, name: client.name };\r\n },\r\n );\r\n\r\n let targetClientOrgId = '';\r\n\r\n const clientSelected = await new Promise((resolve) => {\r\n showSupportOverlay({\r\n text: t('home:supportLoginPrompt'),\r\n options: options,\r\n onCancelClick: () => {\r\n hideSupportOverlay();\r\n resolve(false);\r\n },\r\n onClientSelected: (clientOrgId: string) => {\r\n targetClientOrgId = clientOrgId;\r\n hideSupportOverlay();\r\n resolve(true);\r\n },\r\n });\r\n });\r\n\r\n if (!clientSelected) {\r\n AuthenticationService.logout();\r\n return false;\r\n } else {\r\n localStorage.setItem(OVERRIDE_SUPPORT_OVERLAY, 'true');\r\n localStorage.setItem(TARGET_CLIENT_ORG_ID, targetClientOrgId);\r\n showPageLoadingOverlay();\r\n return await loginUser();\r\n }\r\n };\r\n hidePageLoadingOverlay();\r\n return await loadClientsAndShowOverlay();\r\n } else {\r\n return await loginUser();\r\n }\r\n } catch (error) {\r\n const errorObj = error as Error;\r\n\r\n // NOTE: We want to keep this as a string literal and not use a translation\r\n if (errorObj.message === 'Unlicensed') {\r\n setAllInitialDataIsLoaded(true);\r\n setShouldRedirectUnlicensedUser(true);\r\n } else {\r\n showErrorNotification(t('general:error'), errorObj.message);\r\n setTimeout(() => AuthenticationService.logout(), 5000);\r\n }\r\n\r\n setWalkMeUserInfo(null);\r\n hidePageLoadingOverlay();\r\n\r\n // Don't render the app if the login process failed\r\n return false;\r\n }\r\n } else {\r\n return await loginUser();\r\n }\r\n }\r\n };\r\n\r\n const loginUser = async (): Promise => {\r\n try {\r\n // try to log user in\r\n await AuthenticationService.login(\r\n t('general:unableToAuthenticate'),\r\n t('general:unableToLogin'),\r\n );\r\n // Only setup WalkMe if we're not logging into a targeted client\r\n const targetClientOrgId = localStorage.getItem(TARGET_CLIENT_ORG_ID);\r\n if (!targetClientOrgId) {\r\n const userEmailAddress = AuthenticationService.currentUserInfo?.email || '';\r\n\r\n if (userEmailAddress) {\r\n setWalkMeUserInfo({\r\n userIdentifier: userEmailAddress,\r\n isAdmin: AuthenticationService.currentUserInfo?.userIsAdmin() ?? false,\r\n isProjectAdmin: AuthenticationService.currentUserInfo?.userIsProjectAdmin() ?? false,\r\n isContributor: AuthenticationService.currentUserInfo?.userIsContributor() ?? false,\r\n });\r\n }\r\n }\r\n\r\n NotificationService.connect();\r\n\r\n // If we logged in the user successfully, render the app\r\n return true;\r\n } catch (error) {\r\n const errorObj = error as Error;\r\n\r\n // NOTE: We want to keep this as a string literal and not use a translation\r\n if (errorObj.message === 'Unlicensed') {\r\n setAllInitialDataIsLoaded(true);\r\n setShouldRedirectUnlicensedUser(true);\r\n } else {\r\n showErrorNotification(t('general:error'), errorObj.message);\r\n setTimeout(() => AuthenticationService.logout(), 5000);\r\n }\r\n\r\n setWalkMeUserInfo(null);\r\n\r\n // Don't render the app if the login process failed\r\n return false;\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n const loadSystemSettings = async (): Promise => {\r\n try {\r\n showPageLoadingOverlay();\r\n\r\n // Load any system values globally\r\n const generalConditionsCode = await SystemValuesApi.getSystemValue(\r\n SystemValues.GENERAL_CONDITIONS_CODE,\r\n );\r\n const canLoadSampleData =\r\n (\r\n await SystemValuesApi.getSystemValue(SystemValues.CAN_LOAD_SAMPLE_DATA)\r\n )?.toLowerCase() === 'true';\r\n\r\n setSystemSettings((currValue) => {\r\n return {\r\n ...currValue,\r\n generalConditionsCode: generalConditionsCode,\r\n canLoadSampleData: canLoadSampleData,\r\n };\r\n });\r\n } catch {\r\n showErrorNotification(t('general:error'), t('general:pageLoadError'));\r\n } finally {\r\n hidePageLoadingOverlay();\r\n }\r\n };\r\n\r\n const loadInitialData = async (): Promise => {\r\n if (allInitialDataIsLoaded) {\r\n return;\r\n }\r\n\r\n const shouldRenderApp = await checkUserAuthenticationStatus();\r\n\r\n // If it's not time to render the app yet (e.g. MSAL is handling something),\r\n // don't load system settings or set the allInitialDataIsLoaded flag\r\n if (!shouldRenderApp) {\r\n return;\r\n }\r\n\r\n if (AuthenticationService.userIsLoggedIn()) {\r\n await loadSystemSettings();\r\n }\r\n\r\n setAllInitialDataIsLoaded(true);\r\n };\r\n\r\n loadInitialData();\r\n }, [\r\n allInitialDataIsLoaded,\r\n hidePageLoadingOverlay,\r\n hideSupportOverlay,\r\n history,\r\n location,\r\n setSystemSettings,\r\n setWalkMeUserInfo,\r\n showErrorNotification,\r\n showPageLoadingOverlay,\r\n showSuccessNotification,\r\n showSupportOverlay,\r\n t,\r\n ]);\r\n\r\n // Redirect unlicensed user\r\n //\r\n // NOTE: Originally we were doing this in the initial data load useEffect above,\r\n // but we were hitting a race condition where the redirect wouldn't work. This\r\n // is because we don't render the unlicensed route til allInitialDataIsLoaded = true\r\n useEffect(() => {\r\n if (allInitialDataIsLoaded && shouldRedirectUnlicensedUser) {\r\n // Explicitly replace the current URL\r\n history.replace(ApplicationRoutes.ERROR_UNLICENSED);\r\n }\r\n }, [allInitialDataIsLoaded, history, shouldRedirectUnlicensedUser]);\r\n\r\n useBeforeunload(() => NotificationService.disconnect());\r\n\r\n // Watch when the user scrolls so we can set a globally accessible observable\r\n useLayoutEffect(() => {\r\n let scrollEventTimer: NodeJS.Timeout;\r\n\r\n const scrollEventHandler = (): void => {\r\n if (scrollEventTimer) {\r\n clearTimeout(scrollEventTimer);\r\n }\r\n\r\n scrollEventTimer = setTimeout(() => {\r\n // Only trigger the observables if the scroll position actually changed\r\n if (window.pageXOffset !== lastValue_ScrollX.current) {\r\n setPageScroll_X(window.pageXOffset);\r\n\r\n lastValue_ScrollX.current = window.pageXOffset;\r\n }\r\n\r\n if (window.pageYOffset !== lastValue_ScrollY.current) {\r\n setPageScroll_Y(window.pageYOffset);\r\n\r\n lastValue_ScrollY.current = window.pageYOffset;\r\n }\r\n }, 125);\r\n };\r\n\r\n window.addEventListener('scroll', scrollEventHandler, { passive: true });\r\n\r\n return (): void => {\r\n clearTimeout(scrollEventTimer);\r\n window.removeEventListener('scroll', scrollEventHandler);\r\n };\r\n }, [setPageScroll_X, setPageScroll_Y]);\r\n\r\n // Watch when the window resizes so we can set a globally accessible observable\r\n useLayoutEffect(() => {\r\n let resizeEventTimer: NodeJS.Timeout;\r\n\r\n const resizeEventHandler = (): void => {\r\n if (resizeEventTimer) {\r\n clearTimeout(resizeEventTimer);\r\n }\r\n\r\n resizeEventTimer = setTimeout(() => {\r\n // Only trigger the observables if the window size actually changed\r\n if (\r\n window.innerHeight !== lastValue_WindowSize.current.height ||\r\n window.innerWidth !== lastValue_WindowSize.current.width\r\n ) {\r\n setWindowResize({\r\n height: window.innerHeight,\r\n width: window.innerWidth,\r\n });\r\n }\r\n }, 100);\r\n };\r\n\r\n window.addEventListener('resize', resizeEventHandler, { passive: true });\r\n\r\n return (): void => {\r\n clearTimeout(resizeEventTimer);\r\n window.removeEventListener('resize', resizeEventHandler);\r\n };\r\n }, [setWindowResize]);\r\n\r\n return (\r\n \r\n <>\r\n {/* We wait until all initial data is loaded before we render any other page components */}\r\n {allInitialDataIsLoaded && (\r\n \r\n \r\n {/* Login page */}\r\n \r\n\r\n {/* Home page */}\r\n \r\n\r\n {/* Bid Package page */}\r\n \r\n\r\n {/* Bid Summary page */}\r\n \r\n\r\n {/* User Permissions page */}\r\n \r\n\r\n {/* Bid Package Maintenance page */}\r\n \r\n\r\n {/* Fees page */}\r\n \r\n\r\n {/* General Conditions page */}\r\n \r\n\r\n {/* General Requirements page */}\r\n \r\n\r\n {/* Project page */}\r\n \r\n \r\n \r\n\r\n {/* Units of Measure page */}\r\n \r\n\r\n {/* Preferences page */}\r\n \r\n\r\n {/* Admin - Frozen Entities page */}\r\n \r\n\r\n {/* Error pages */}\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n \r\n \r\n );\r\n};\r\n\r\nexport default App;\r\n","import { library } from '@fortawesome/fontawesome-svg-core';\r\nimport {\r\n faFileArchive as farFileArchive,\r\n faSquare as farSquare,\r\n} from '@fortawesome/free-regular-svg-icons';\r\nimport {\r\n faArrowDown,\r\n faArrowUp,\r\n faBars,\r\n faBuilding,\r\n faChartBar,\r\n faCheck,\r\n faCheckCircle,\r\n faCheckSquare,\r\n faChevronDown,\r\n faCircle,\r\n faCog,\r\n faColumns,\r\n faCopy,\r\n faDatabase,\r\n faDollarSign,\r\n faEdit,\r\n faEllipsisV,\r\n faEnvelope,\r\n faExclamationTriangle,\r\n faFileAlt,\r\n faFileExcel,\r\n faFileImage,\r\n faFilePdf,\r\n faFileWord,\r\n faGripHorizontal,\r\n faHeadset,\r\n faInfoCircle,\r\n faKeyboard,\r\n faList,\r\n faLock,\r\n faLockOpen,\r\n faMinusSquare,\r\n faPaste,\r\n faPhoneAlt,\r\n faPlus,\r\n faPlusSquare,\r\n faSearch,\r\n faSlash,\r\n faSortAmountDownAlt,\r\n faSortAmountUpAlt,\r\n faSpinner,\r\n faSquare,\r\n faStickyNote,\r\n faTh,\r\n faTimes,\r\n faTrash,\r\n faTrophy,\r\n faUser,\r\n faUsers,\r\n faWifi,\r\n faWindowMaximize,\r\n faWindowMinimize,\r\n faWindowRestore,\r\n} from '@fortawesome/free-solid-svg-icons';\r\n\r\nconst initializeFontAwesomeIcons = (): void => {\r\n // Add commonly used icons to the library collection so they're available\r\n // in every component without explicit imports\r\n library.add(\r\n faArrowDown,\r\n faArrowUp,\r\n faBars,\r\n faBuilding,\r\n faChartBar,\r\n faCheck,\r\n faCheckCircle,\r\n faCheckSquare,\r\n faChevronDown,\r\n faCircle,\r\n faCog,\r\n faColumns,\r\n faCopy,\r\n faDatabase,\r\n faDollarSign,\r\n faEdit,\r\n faEllipsisV,\r\n faEnvelope,\r\n faExclamationTriangle,\r\n faFileAlt,\r\n faFileExcel,\r\n faFileImage,\r\n faFilePdf,\r\n faFileWord,\r\n faGripHorizontal,\r\n faHeadset,\r\n faInfoCircle,\r\n faKeyboard,\r\n faList,\r\n faLock,\r\n faLockOpen,\r\n faMinusSquare,\r\n faPaste,\r\n faPhoneAlt,\r\n faPlus,\r\n faPlusSquare,\r\n faSearch,\r\n faSlash,\r\n faSortAmountDownAlt,\r\n faSortAmountUpAlt,\r\n faSpinner,\r\n faSquare,\r\n faSquare,\r\n faStickyNote,\r\n faTh,\r\n faTimes,\r\n faTrash,\r\n faTrophy,\r\n faUser,\r\n faUsers,\r\n faWifi,\r\n faWindowMaximize,\r\n faWindowMinimize,\r\n faWindowRestore,\r\n farFileArchive,\r\n farSquare,\r\n );\r\n};\r\n\r\nexport { initializeFontAwesomeIcons };\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { MutableRefObject, useContext, useEffect, useRef, useState } from 'react';\r\nimport { Subscription } from 'rxjs';\r\nimport GeneralConstants from '../../../constants/general';\r\nimport BTButton from '../controls/button/BTButton';\r\nimport './ConfirmationOverlay.scss';\r\nimport {\r\n ConfirmationOverlayContext,\r\n ConfirmationOverlayDisplayInfo,\r\n} from './ConfirmationOverlayContext';\r\n\r\nconst ConfirmationOverlay: React.FC = () => {\r\n const { confirmationOverlaySet$, hideConfirmationOverlay } = useContext(\r\n ConfirmationOverlayContext,\r\n );\r\n\r\n const firstButtonRef: MutableRefObject = useRef(null);\r\n const lastButtonRef: MutableRefObject = useRef(null);\r\n\r\n const [confirmationOverlayDisplayInfo, setConfirmationOverlayDisplayInfo] = useState<\r\n ConfirmationOverlayDisplayInfo\r\n >({\r\n currentConfirmationOverlayParameters: null,\r\n hasBeenToggled: false,\r\n isDisplayed: false,\r\n });\r\n\r\n const loadingPageOverlayCssClasses = ['confirmationOverlay'];\r\n\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n confirmationOverlaySet$.subscribe((data) => {\r\n setConfirmationOverlayDisplayInfo(data);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [confirmationOverlaySet$]);\r\n\r\n // Don't even show the overlay if it hasn't explicitly been toggled\r\n if (!confirmationOverlayDisplayInfo.hasBeenToggled) {\r\n loadingPageOverlayCssClasses.push('d-none');\r\n } else if (confirmationOverlayDisplayInfo.isDisplayed) {\r\n loadingPageOverlayCssClasses.push('isDisplayed');\r\n }\r\n\r\n const onTab = (event: React.KeyboardEvent): void => {\r\n if (event.shiftKey) {\r\n if (document.activeElement === firstButtonRef.current) {\r\n event.preventDefault();\r\n (lastButtonRef.current as HTMLButtonElement).focus();\r\n }\r\n } else {\r\n //if tabbing forward\r\n if (document.activeElement === lastButtonRef.current) {\r\n event.preventDefault();\r\n (firstButtonRef.current as HTMLButtonElement).focus();\r\n }\r\n }\r\n };\r\n\r\n // Focus overlay params if not null\r\n useEffect(() => {\r\n if (confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters) {\r\n (firstButtonRef.current as HTMLButtonElement).focus();\r\n }\r\n }, [confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters]);\r\n\r\n return (\r\n {\r\n // If there is only one button, it's probably important that the user click it (or else why wouldn't we have 2?)\r\n // so disable exiting out of this with the keyboard\r\n if (\r\n (confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters?.buttons?.length ??\r\n 0) > 1\r\n ) {\r\n const allowEscapeKey =\r\n confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters?.allowEscapeKey ??\r\n true;\r\n\r\n // Hide the overlay when the escape key is pressed\r\n if (allowEscapeKey && event.key === GeneralConstants.KEY_ESCAPE) {\r\n hideConfirmationOverlay();\r\n }\r\n }\r\n\r\n // Restrict tabbing to the overlay buttons\r\n if (event.key === GeneralConstants.KEY_TAB) {\r\n onTab(event);\r\n }\r\n }}\r\n >\r\n
    \r\n {confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters?.image ===\r\n 'bid-day-logo' ? (\r\n <>\r\n
    \r\n \"confirmation\"\r\n
    \r\n
    \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters?.image === 'excel' ? (\r\n <>\r\n
    \r\n \r\n
    \r\n
    \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n {confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters?.text}\r\n
    \r\n\r\n {confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters?.text2 ? (\r\n <>\r\n
    \r\n\r\n
    \r\n {confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters.text2}\r\n
    \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n
    \r\n\r\n
    \r\n {confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters?.buttons.map(\r\n (currButton, index) => {\r\n const checkIfLastItem = (\r\n index: number,\r\n ): MutableRefObject | null => {\r\n if (\r\n index ===\r\n (confirmationOverlayDisplayInfo.currentConfirmationOverlayParameters?.buttons\r\n ?.length ?? 0) -\r\n 1\r\n ) {\r\n return lastButtonRef;\r\n } else {\r\n return null;\r\n }\r\n };\r\n\r\n return (\r\n \r\n );\r\n },\r\n )}\r\n
    \r\n
    \r\n \r\n );\r\n};\r\n\r\nexport default ConfirmationOverlay;\r\n","import React, { useCallback, useContext, useEffect, useState } from 'react';\r\nimport { Subscription } from 'rxjs';\r\nimport GeneralConstants from '../../../../constants/general';\r\nimport { BTGeneralContext } from '../../general-contexts/BTGeneralContext';\r\nimport './EEBalloons.scss';\r\n\r\nconst balloonsLetters = 'Bid Day'.split('');\r\n\r\nconst EEBalloons: React.FC = () => {\r\n const { userJustGotTheLatestUpdate$ } = useContext(BTGeneralContext);\r\n\r\n const [balloonsAreDisplayed, setBalloonsAreDisplayed] = useState(false);\r\n\r\n const displayBalloons = useCallback(() => {\r\n if (balloonsAreDisplayed) {\r\n return;\r\n }\r\n\r\n setBalloonsAreDisplayed(true);\r\n\r\n setTimeout(() => {\r\n setBalloonsAreDisplayed(false);\r\n }, 10000);\r\n }, [balloonsAreDisplayed]);\r\n\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n // Listen for an event that the user got the latest app update\r\n // and show the balloons if so because it's worth partying over\r\n allSubscriptions.add(\r\n userJustGotTheLatestUpdate$.subscribe(() => {\r\n displayBalloons();\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [displayBalloons, userJustGotTheLatestUpdate$]);\r\n\r\n // Let the user trigger this by pressing a special hotkey\r\n useEffect(() => {\r\n const onKeyDown = (e: KeyboardEvent) => {\r\n if (e.altKey && e.ctrlKey && e.shiftKey && e.key === GeneralConstants.KEY_B) {\r\n displayBalloons();\r\n }\r\n };\r\n\r\n document.body.addEventListener('keydown', onKeyDown, { passive: true });\r\n\r\n return () => {\r\n document.body.removeEventListener('keydown', onKeyDown);\r\n };\r\n }, [displayBalloons]);\r\n\r\n return balloonsAreDisplayed ? (\r\n
    \r\n {balloonsLetters.map((v, i) => {\r\n return (\r\n
    \r\n {v}\r\n
    \r\n );\r\n })}\r\n
    \r\n ) : (\r\n <>\r\n );\r\n};\r\n\r\nexport default EEBalloons;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { useContext, useEffect, useState } from 'react';\r\nimport { Subscription } from 'rxjs';\r\nimport './FloatingLoadingIndicator.scss';\r\nimport {\r\n FloatingIndicatorDisplayInfo,\r\n FloatingLoadingIndicatorContext,\r\n} from './FloatingLoadingIndicatorContext';\r\n\r\nconst FloatingLoadingIndicator: React.FC = () => {\r\n const {\r\n floatingLoadingIndicatorDisplayInfo_Blue$,\r\n floatingLoadingIndicatorDisplayInfo_Green$,\r\n } = useContext(FloatingLoadingIndicatorContext);\r\n\r\n const [\r\n floatingLoadingIndicatorDisplayInfo_Blue,\r\n setFloatingLoadingIndicatorDisplayInfo_Blue,\r\n ] = useState(null);\r\n\r\n const [\r\n floatingLoadingIndicatorDisplayInfo_Green,\r\n setFloatingLoadingIndicatorDisplayInfo_Green,\r\n ] = useState(null);\r\n\r\n // Listen for observable events\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n floatingLoadingIndicatorDisplayInfo_Blue$.subscribe((data) => {\r\n setFloatingLoadingIndicatorDisplayInfo_Blue(data);\r\n }),\r\n );\r\n\r\n allSubscriptions.add(\r\n floatingLoadingIndicatorDisplayInfo_Green$.subscribe((data) => {\r\n setFloatingLoadingIndicatorDisplayInfo_Green(data);\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [floatingLoadingIndicatorDisplayInfo_Blue$, floatingLoadingIndicatorDisplayInfo_Green$]);\r\n\r\n const counter_Blue = floatingLoadingIndicatorDisplayInfo_Blue?.counter ?? 0;\r\n const counter_Green = floatingLoadingIndicatorDisplayInfo_Green?.counter ?? 0;\r\n\r\n return (\r\n <>\r\n 0 ? 'isDisplayed' : ''}`}\r\n >\r\n {floatingLoadingIndicatorDisplayInfo_Blue?.text}\r\n\r\n 0 ? 'isSpinning' : ''}`}\r\n icon=\"spinner\"\r\n />\r\n \r\n\r\n 0 ? 'isDisplayed' : ''\r\n }`}\r\n >\r\n {floatingLoadingIndicatorDisplayInfo_Green?.text}\r\n\r\n 0 ? 'isSpinning' : ''}`}\r\n icon=\"spinner\"\r\n />\r\n \r\n \r\n );\r\n};\r\n\r\nexport default FloatingLoadingIndicator;\r\n","import React from 'react';\r\nimport './LoadingIndicator.scss';\r\n\r\nconst LoadingIndicator: React.FC = () => {\r\n return
    ;\r\n};\r\n\r\nexport default LoadingIndicator;\r\n","import React, { useContext, useEffect, useState } from 'react';\r\nimport { Subscription } from 'rxjs';\r\nimport LoadingIndicator from '../loading-indicator/LoadingIndicator';\r\nimport './LoadingPageOverlay.scss';\r\nimport { LoadingPageOverlayContext } from './LoadingPageOverlayContext';\r\n\r\nconst LoadingPageOverlay: React.FC = () => {\r\n const { loadingOverlayCounter$ } = useContext(LoadingPageOverlayContext);\r\n\r\n const [loadingOverlayCounter, setLoadingOverlayCounter] = useState(0);\r\n\r\n // Listen for observable events\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n loadingOverlayCounter$.subscribe((data) => {\r\n // When this event comes in, we want to update the state variable on a new task via setTimeout.\r\n // If we don't, this can cause signficant UI blockage as things are rendering and fighting for CPU\r\n // resources.\r\n setTimeout(() => {\r\n setLoadingOverlayCounter(data);\r\n });\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [loadingOverlayCounter$]);\r\n\r\n const loadingPageOverlayCssClasses = ['loadingPageOverlay'];\r\n\r\n if (loadingOverlayCounter > 0) {\r\n loadingPageOverlayCssClasses.push('isDisplayed');\r\n }\r\n\r\n return (\r\n
    \r\n
    {loadingOverlayCounter > 0 ? : <>}
    \r\n
    \r\n );\r\n};\r\n\r\nexport default LoadingPageOverlay;\r\n","import React, { useCallback, useContext, useEffect, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Subscription } from 'rxjs';\r\nimport { isSmallScreenDevice } from '../../../utils/general';\r\nimport BTButton from '../controls/button/BTButton';\r\nimport { BTGeneralContext } from '../general-contexts/BTGeneralContext';\r\nimport './MobileDeviceOverlay.scss';\r\n\r\nconst MobileDeviceOverlay: React.FC = () => {\r\n const { windowResize$ } = useContext(BTGeneralContext);\r\n\r\n const { t } = useTranslation();\r\n\r\n const [overrideWarning, setOverrideWarning] = useState(false);\r\n\r\n const setBodyCSSClass = useCallback(\r\n (displayOverride: boolean | null) => {\r\n const shouldDisplayOverlay = displayOverride ?? (isSmallScreenDevice() && !overrideWarning);\r\n\r\n // If we want to display this overlay because the user is on an unsupported screen resolution,\r\n // we also need to add a class to the body so we can hide things on the page, which will also allow the\r\n // fixed position of this overlay to work correctly and not have any scrollable content around it.\r\n const pageCannotBeViewedOnSmallDevice = 'pageCannotBeViewedOnSmallDevice';\r\n\r\n if (shouldDisplayOverlay) {\r\n document.body.classList.add(pageCannotBeViewedOnSmallDevice);\r\n } else {\r\n document.body.classList.remove(pageCannotBeViewedOnSmallDevice);\r\n }\r\n },\r\n [overrideWarning],\r\n );\r\n\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n windowResize$.subscribe((v) => {\r\n setBodyCSSClass(null);\r\n }),\r\n );\r\n\r\n return () => {\r\n allSubscriptions.unsubscribe();\r\n };\r\n }, [setBodyCSSClass, windowResize$]);\r\n\r\n // When this component mounts, check if we need to set things\r\n useEffect(() => {\r\n setBodyCSSClass(null);\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n return !overrideWarning ? (\r\n
    \r\n
    \r\n \"Bid\r\n\r\n
    \r\n {t('general:smallDevice_Message1')}\r\n
    \r\n {t('general:smallDevice_Message2')}\r\n
    \r\n\r\n
    \r\n\r\n {\r\n setOverrideWarning(true);\r\n setBodyCSSClass(false);\r\n }}\r\n />\r\n
    \r\n
    \r\n ) : (\r\n <>\r\n );\r\n};\r\n\r\nexport default MobileDeviceOverlay;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Subscription } from 'rxjs';\r\nimport './NotificationPanel.scss';\r\nimport {\r\n NotificationPanelContext,\r\n NotificationPanelMessage,\r\n NotificationPanelTypes,\r\n} from './NotificationPanelContext';\r\n\r\ninterface Props {\r\n testTimeout?: number;\r\n}\r\n\r\nconst DEFAULT_TIMEOUT_IN_MS = 5_000;\r\n\r\nconst NotificationPanel: React.FC = (props) => {\r\n const { t } = useTranslation();\r\n\r\n const { queuedNotifications$, setQueuedNotifications } = useContext(NotificationPanelContext);\r\n\r\n const queuedNotificationsCopy = useRef([]);\r\n\r\n const [\r\n notificationBeingDisplayed,\r\n setNotificationBeingDisplayed,\r\n ] = useState(null);\r\n\r\n const notificationBeingDisplayedCopy = useRef(null);\r\n\r\n const [isDisplayed, setIsDisplayed] = useState(false);\r\n\r\n const hideCurrentNotificationTimeoutPromise = useRef(null);\r\n\r\n const notificationTimeout = props.testTimeout || DEFAULT_TIMEOUT_IN_MS;\r\n\r\n const showNextNotification = useCallback(() => {\r\n if (!queuedNotificationsCopy.current.length) {\r\n return;\r\n }\r\n\r\n const copy = [...queuedNotificationsCopy.current];\r\n const nextNotification = copy.shift();\r\n\r\n setNotificationBeingDisplayed(nextNotification!);\r\n notificationBeingDisplayedCopy.current = { ...nextNotification! };\r\n\r\n setQueuedNotifications(copy);\r\n\r\n // Stagger things so the UI has time to animate\r\n setTimeout(() => {\r\n setIsDisplayed(true);\r\n }, 250);\r\n\r\n if (hideCurrentNotificationTimeoutPromise.current) {\r\n clearTimeout(hideCurrentNotificationTimeoutPromise.current);\r\n }\r\n\r\n hideCurrentNotificationTimeoutPromise.current = setTimeout(() => {\r\n setIsDisplayed(false);\r\n\r\n setTimeout(() => {\r\n setNotificationBeingDisplayed(null);\r\n notificationBeingDisplayedCopy.current = null;\r\n }, 500);\r\n\r\n setTimeout(() => {\r\n showNextNotification();\r\n }, 600);\r\n }, notificationTimeout);\r\n }, [notificationTimeout, setQueuedNotifications]);\r\n\r\n // Listen for observable events\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n allSubscriptions.add(\r\n queuedNotifications$.subscribe((data) => {\r\n // When the notifications queue changes, update the local copy in this component\r\n queuedNotificationsCopy.current = [...data];\r\n\r\n // Show the notification if one isn't displayed currently\r\n if (!notificationBeingDisplayedCopy.current) {\r\n setTimeout(() => {\r\n showNextNotification();\r\n }, 0);\r\n }\r\n }),\r\n );\r\n\r\n return () => allSubscriptions.unsubscribe();\r\n }, [queuedNotifications$, showNextNotification]);\r\n\r\n const cssClassesArray = ['notificationPanel', isDisplayed ? 'isDisplayed' : ''];\r\n\r\n if (notificationBeingDisplayed) {\r\n switch (notificationBeingDisplayed.type) {\r\n case NotificationPanelTypes.Success:\r\n cssClassesArray.push('success');\r\n break;\r\n case NotificationPanelTypes.Error:\r\n cssClassesArray.push('error');\r\n break;\r\n case NotificationPanelTypes.Info:\r\n cssClassesArray.push('info');\r\n break;\r\n case NotificationPanelTypes.Warning:\r\n cssClassesArray.push('warning');\r\n break;\r\n }\r\n }\r\n\r\n return (\r\n {\r\n if (hideCurrentNotificationTimeoutPromise.current) {\r\n clearTimeout(hideCurrentNotificationTimeoutPromise.current);\r\n }\r\n\r\n setIsDisplayed(false);\r\n\r\n setTimeout(() => {\r\n setNotificationBeingDisplayed(null);\r\n notificationBeingDisplayedCopy.current = null;\r\n }, 500);\r\n\r\n setTimeout(() => {\r\n showNextNotification();\r\n }, 600);\r\n }}\r\n >\r\n {notificationBeingDisplayed ? (\r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n\r\n
    {notificationBeingDisplayed.title}
    \r\n\r\n
    {notificationBeingDisplayed.message}
    \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n )}\r\n \r\n );\r\n};\r\n\r\nexport default NotificationPanel;\r\n","import React, { useContext, useEffect, useRef, useState } from 'react';\r\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useLocation } from 'react-router';\r\nimport { Popover, PopoverBody } from 'reactstrap';\r\nimport { BTPopoverContext, BTPopoverInfo } from './BTPopoverContext';\r\nimport './BTPopover.scss';\r\n\r\nconst BTPopover: React.FC = () => {\r\n const { t } = useTranslation();\r\n const location = useLocation();\r\n\r\n const { displayedPopoverInfo$, setDisplayedPopoverInfo } = useContext(BTPopoverContext);\r\n\r\n // A local copy of the last displayed popover info that was sent on the observable\r\n const [displayedPopoverInfoCopy, setDisplayedPopoverInfoCopy] = useState(\r\n null,\r\n );\r\n\r\n const hidePopoverTimeout = useRef();\r\n\r\n // Listen for any updates that any other context menu was opened on the page\r\n useEffect(() => {\r\n const subscription = displayedPopoverInfo$.subscribe((newInfo: BTPopoverInfo | null) => {\r\n setDisplayedPopoverInfoCopy(null);\r\n\r\n // The Reactstrap popover won't re-render unless we hide and show it fresh, so null things out\r\n // and immediately set them to the new info on a new task so React will finish its render cycle first\r\n if (newInfo !== null) {\r\n setTimeout(() => {\r\n setDisplayedPopoverInfoCopy(newInfo);\r\n });\r\n }\r\n });\r\n\r\n return () => subscription.unsubscribe();\r\n }, [displayedPopoverInfo$, displayedPopoverInfoCopy]);\r\n\r\n // When the URL changes, we want to hide any popovers\r\n useEffect(() => {\r\n setDisplayedPopoverInfoCopy(null);\r\n }, [location]);\r\n\r\n return displayedPopoverInfoCopy !== null ? (\r\n {\r\n setDisplayedPopoverInfo(null);\r\n }}\r\n fade={false}\r\n onMouseOut={() => {\r\n // When the user's mouse leaves the popover for a certain amount of time, we want to close it\r\n if (hidePopoverTimeout.current) {\r\n clearTimeout(hidePopoverTimeout.current);\r\n }\r\n\r\n hidePopoverTimeout.current = setTimeout(() => {\r\n setDisplayedPopoverInfo(null);\r\n }, 500);\r\n }}\r\n >\r\n {\r\n // If the user is moving the mouse over the popover, prevent any events that would cause it to close\r\n if (hidePopoverTimeout.current) {\r\n clearTimeout(hidePopoverTimeout.current);\r\n }\r\n\r\n hidePopoverTimeout.current = undefined;\r\n }}\r\n >\r\n {displayedPopoverInfoCopy.showCloseButton ? (\r\n {\r\n setDisplayedPopoverInfo(null);\r\n }}\r\n title={t('general:close')}\r\n >\r\n \r\n \r\n ) : (\r\n <>\r\n )}\r\n\r\n {displayedPopoverInfoCopy.title ? (\r\n
    {displayedPopoverInfoCopy.title}
    \r\n ) : (\r\n <>\r\n )}\r\n\r\n {displayedPopoverInfoCopy.text ? (\r\n
    {displayedPopoverInfoCopy.text}
    \r\n ) : (\r\n <>\r\n )}\r\n \r\n \r\n ) : (\r\n <>\r\n );\r\n};\r\n\r\nexport default BTPopover;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\r\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Subscription } from 'rxjs';\r\nimport { LOCAL_STORAGE_KEY_UPDATED_TO_NEW_VERSION } from '../../../utils/hooks/useVersionCheck';\r\nimport { BTGeneralContext } from '../general-contexts/BTGeneralContext';\r\nimport './ReloadAppTimer.scss';\r\n\r\nconst TIMER_TIME = 2 * 60; // 2 minutes\r\n\r\nconst ReloadAppTimer: React.FC = () => {\r\n const [isDisplayed, setIsDisplayed] = useState(false);\r\n\r\n const { t } = useTranslation();\r\n\r\n const [timeRemaining, setTimeRemaining] = useState(TIMER_TIME);\r\n\r\n const { appWillRestart$ } = useContext(BTGeneralContext);\r\n\r\n const reloadPage = () => {\r\n if (counterTimeout.current) {\r\n clearTimeout(counterTimeout.current);\r\n }\r\n\r\n counterTimeout.current = null;\r\n\r\n // Set a local storage value, so when the app reloads, it knows the user just updated and shows them a message\r\n // that they're running the latest version of Bid Day\r\n localStorage.setItem(LOCAL_STORAGE_KEY_UPDATED_TO_NEW_VERSION, JSON.stringify(true));\r\n\r\n document.location.reload();\r\n };\r\n\r\n const counterTimeout = useRef(null);\r\n\r\n const decrementCounter = useCallback(() => {\r\n setTimeRemaining((v) => Math.max(0, v - 1));\r\n\r\n // NOTE: As this is JavaScript, this timer is hardly super accurate since it works with timeouts,\r\n // but it's good enough for what we're doing here.\r\n counterTimeout.current = setTimeout(() => {\r\n decrementCounter();\r\n }, 1000);\r\n\r\n // NOTE: We intentionally do not clean up the timeout when this function gets updated when dependencies change.\r\n // We clean it up in a useEffect below.\r\n }, []);\r\n\r\n // Clean up the timeout if this component unmounts\r\n useEffect(() => {\r\n return () => {\r\n if (counterTimeout.current) {\r\n clearTimeout(counterTimeout.current);\r\n }\r\n };\r\n }, []);\r\n\r\n // Listen for changes to the time remaining variable and reload the page when it reaches 0\r\n useEffect(() => {\r\n if (timeRemaining === 0) {\r\n reloadPage();\r\n }\r\n }, [timeRemaining]);\r\n\r\n useEffect(() => {\r\n const allSubscriptions = new Subscription();\r\n\r\n // Listen for the event that the app should restart and show the timer / handle reloading the page\r\n // after the timer elapses\r\n allSubscriptions.add(\r\n appWillRestart$.subscribe(() => {\r\n setIsDisplayed(true);\r\n\r\n setTimeout(() => {\r\n decrementCounter();\r\n }, 1000);\r\n }),\r\n );\r\n\r\n return () => {\r\n allSubscriptions.unsubscribe();\r\n };\r\n }, [appWillRestart$, decrementCounter, timeRemaining]);\r\n\r\n const getMinutesString = (): string => {\r\n return Math.floor(timeRemaining / 60).toString();\r\n };\r\n\r\n const getSecondsString = (): string => {\r\n const secondsRemaining = timeRemaining % 60;\r\n\r\n return secondsRemaining < 10 ? `0${secondsRemaining}` : secondsRemaining.toString();\r\n };\r\n\r\n return isDisplayed ? (\r\n
    \r\n
    \r\n {getMinutesString()}:{getSecondsString()}\r\n
    \r\n\r\n
    {t('general:untilBidDayUpdates')}
    \r\n\r\n
    \r\n {t('general:getLatestVersion')}\r\n \r\n
    \r\n
    \r\n ) : (\r\n <>\r\n );\r\n};\r\n\r\nexport default ReloadAppTimer;\r\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport React, {\n MutableRefObject,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Subscription } from 'rxjs';\nimport GeneralConstants from '../../../constants/general';\nimport BTButton from '../controls/button/BTButton';\nimport BTDropDownList from '../inputs/BTDropDownList';\nimport './SupportOverlay.scss';\nimport { SupportOverlayContext, SupportOverlayDisplayInfo } from './SupportOverlayContext';\n\nconst SupportOverlay: React.FC = () => {\n const { t } = useTranslation();\n const { supportOverlaySet$ } = useContext(SupportOverlayContext);\n\n const firstButtonRef: MutableRefObject = useRef(null);\n const lastButtonRef: MutableRefObject = useRef(null);\n\n const [supportOverlayDisplayInfo, setSupportOverlayDisplayInfo] = useState<\n SupportOverlayDisplayInfo\n >({\n currentSupportOverlayParameters: null,\n hasBeenToggled: false,\n isDisplayed: false,\n });\n\n const loadingPageOverlayCssClasses = ['supportOverlay'];\n\n const [selectedClient, setSelectedClient] = useState();\n\n // Sets up the subscription that handles displaying the overlay\n useEffect(() => {\n const allSubscriptions = new Subscription();\n\n allSubscriptions.add(\n supportOverlaySet$.subscribe((data) => {\n setSupportOverlayDisplayInfo(data);\n }),\n );\n\n return () => allSubscriptions.unsubscribe();\n }, [supportOverlaySet$]);\n\n // Sets up the default clientOrgId on the initial render\n useEffect(() => {\n const defaultClientOrgId = (supportOverlayDisplayInfo.currentSupportOverlayParameters?.options.find(\n (client) => client.name === 'Beck Technology',\n )?.value ||\n supportOverlayDisplayInfo.currentSupportOverlayParameters?.options[0].value ||\n '') as string;\n\n setSelectedClient(defaultClientOrgId);\n }, [\n supportOverlayDisplayInfo.currentSupportOverlayParameters,\n supportOverlayDisplayInfo.currentSupportOverlayParameters?.options,\n ]);\n\n // Don't even show the overlay if it hasn't explicitly been toggled\n if (!supportOverlayDisplayInfo.hasBeenToggled) {\n loadingPageOverlayCssClasses.push('d-none');\n } else if (supportOverlayDisplayInfo.isDisplayed) {\n loadingPageOverlayCssClasses.push('isDisplayed');\n }\n\n const onTab = (event: React.KeyboardEvent): void => {\n if (event.shiftKey) {\n if (document.activeElement === firstButtonRef.current) {\n event.preventDefault();\n (lastButtonRef.current as HTMLButtonElement).focus();\n }\n } else {\n //if tabbing forward\n if (document.activeElement === lastButtonRef.current) {\n event.preventDefault();\n (firstButtonRef.current as HTMLButtonElement).focus();\n }\n }\n };\n\n const selectedClientChangeHandler = useCallback((clientOrgId: unknown) => {\n // Set local definition state\n const selectedClientOrgId = clientOrgId as string;\n setSelectedClient(selectedClientOrgId);\n }, []);\n\n return (\n {\n // Restrict tabbing to the overlay buttons\n if (event.key === GeneralConstants.KEY_TAB) {\n onTab(event);\n }\n }}\n >\n
    \n
    \n \n
    \n
    \n
    \n {supportOverlayDisplayInfo.currentSupportOverlayParameters?.text}\n
    \n
    \n\n {supportOverlayDisplayInfo.currentSupportOverlayParameters ? (\n
    \n
    \n \n
    \n
    \n ) : (\n <>\n )}\n\n
    \n\n
    \n \n {\n supportOverlayDisplayInfo.currentSupportOverlayParameters?.onClientSelected(\n selectedClient || '',\n );\n }}\n />\n
    \n
    \n \n );\n};\n\nexport default SupportOverlay;\n","//\r\n// NOTE: TO ADD SUPPORT FOR ANOTHER LOCALE, REFER TO THE WIKI ARTICLE FOR INSTRUCTIONS\r\n//\r\n\r\nimport { load } from '@progress/kendo-react-intl';\r\nimport { initReactI18next } from 'react-i18next';\r\nimport i18n, { Resource } from 'i18next';\r\nimport { TranslationFilesMap, DEFAULT_LANG, format } from './i18n';\r\nimport { Import } from '../utils/imports';\r\nimport moment from 'moment';\r\n\r\nimport 'moment/locale/fr-ca';\r\n\r\nimport weekData from 'cldr-core/supplemental/weekData.json';\r\nimport frCaGeneric from 'cldr-dates-full/main/fr-CA/ca-generic.json';\r\nimport frCaGregorian from 'cldr-dates-full/main/fr-CA/ca-gregorian.json';\r\nimport frCaDateFields from 'cldr-dates-full/main/fr-CA/dateFields.json';\r\nimport frCaTimeZoneNames from 'cldr-dates-full/main/fr-CA/timeZoneNames.json';\r\n\r\nload(weekData, frCaGeneric, frCaGregorian, frCaDateFields, frCaTimeZoneNames);\r\n\r\nconst getInitialTranslations = (): Resource => {\r\n const resources: Resource = { [DEFAULT_LANG]: {} };\r\n const getTranslationsFunc = TranslationFilesMap[DEFAULT_LANG] as () => Import[];\r\n const translationFiles = getTranslationsFunc();\r\n\r\n translationFiles.forEach((translationFile) => {\r\n resources[DEFAULT_LANG][translationFile.name] = translationFile.translations;\r\n });\r\n\r\n return resources;\r\n};\r\n\r\ni18n\r\n .use(initReactI18next) // passes i18n down to react-i18next\r\n .init({\r\n resources: getInitialTranslations(),\r\n lng: DEFAULT_LANG,\r\n interpolation: {\r\n escapeValue: false, // react already safes from xss\r\n format: format,\r\n },\r\n });\r\n\r\n// Set initial moment locale to the default language\r\nmoment.locale(DEFAULT_LANG);\r\n","// In production, we register a service worker to serve assets from local cache.\r\n\r\n// This lets the app load faster on subsequent visits in production, and gives\r\n// it offline capabilities. However, it also means that developers (and users)\r\n// will only see deployed updates on the \"N+1\" visit to a page, since previously\r\n// cached resources are updated in the background.\r\n\r\n// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.\r\n// This link also includes instructions on opting out of this behavior.\r\n\r\nconst isLocalhost = Boolean(\r\n window.location.hostname === 'localhost' ||\r\n // [::1] is the IPv6 localhost address.\r\n window.location.hostname === '[::1]' ||\r\n // 127.0.0.1/8 is considered localhost for IPv4.\r\n window.location.hostname.match(/^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/),\r\n);\r\n\r\nexport default function register(): void {\r\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\r\n // The URL constructor is available in all browsers that support SW.\r\n const publicUrl = new URL(\r\n (process as { env: { [key: string]: string } }).env.PUBLIC_URL,\r\n window.location.href,\r\n );\r\n\r\n if (publicUrl.origin !== window.location.origin) {\r\n // Our service worker won't work if PUBLIC_URL is on a different origin\r\n // from what our page is served on. This might happen if a CDN is used to\r\n // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374\r\n return;\r\n }\r\n\r\n window.addEventListener('load', () => {\r\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\r\n\r\n if (isLocalhost) {\r\n // This is running on localhost. Lets check if a service worker still exists or not.\r\n checkValidServiceWorker(swUrl);\r\n } else {\r\n // Is not local host. Just register service worker\r\n registerValidSW(swUrl);\r\n }\r\n });\r\n }\r\n}\r\n\r\nfunction registerValidSW(swUrl: string) {\r\n navigator.serviceWorker\r\n .register(swUrl)\r\n .then((registration) => {\r\n registration.onupdatefound = () => {\r\n const installingWorker = registration.installing;\r\n if (installingWorker == null) {\r\n return;\r\n }\r\n installingWorker.onstatechange = () => {\r\n if (installingWorker.state === 'installed') {\r\n if (navigator.serviceWorker.controller) {\r\n // At this point, the old content will have been purged and\r\n // the fresh content will have been added to the cache.\r\n // It's the perfect time to display a \"New content is\r\n // available; please refresh.\" message in your web app.\r\n // eslint-disable-next-line no-console\r\n console.log('New content is available; please refresh.');\r\n } else {\r\n // At this point, everything has been precached.\r\n // It's the perfect time to display a\r\n // \"Content is cached for offline use.\" message.\r\n // eslint-disable-next-line no-console\r\n console.log('Content is cached for offline use.');\r\n }\r\n }\r\n };\r\n };\r\n })\r\n .catch((error) => {\r\n // eslint-disable-next-line no-console\r\n console.error('Error during service worker registration:', error);\r\n });\r\n}\r\n\r\nfunction checkValidServiceWorker(swUrl: string) {\r\n // Check if the service worker can be found. If it can't reload the page.\r\n fetch(swUrl)\r\n .then((response) => {\r\n const contentType = response.headers.get('content-type');\r\n\r\n // Ensure service worker exists, and that we really are getting a JS file.\r\n if (\r\n response.status === 404 ||\r\n (contentType != null && contentType.indexOf('javascript') === -1)\r\n ) {\r\n // No service worker found. Probably a different app. Reload the page.\r\n navigator.serviceWorker.ready.then((registration) => {\r\n registration.unregister().then(() => {\r\n window.location.reload();\r\n });\r\n });\r\n } else {\r\n // Service worker found. Proceed as normal.\r\n registerValidSW(swUrl);\r\n }\r\n })\r\n .catch(() => {\r\n // eslint-disable-next-line no-console\r\n console.log('No internet connection found. App is running in offline mode.');\r\n });\r\n}\r\n\r\nexport function unregister(): void {\r\n if ('serviceWorker' in navigator) {\r\n navigator.serviceWorker.ready.then((registration) => {\r\n registration.unregister();\r\n });\r\n }\r\n}\r\n","import 'bootstrap/dist/css/bootstrap.css';\r\nimport { createBrowserHistory } from 'history';\r\nimport React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport { Router } from 'react-router-dom';\r\nimport 'reflect-metadata';\r\nimport App from './App';\r\nimport ConfirmationOverlay from './app/common-page-components/confirmation-overlay/ConfirmationOverlay';\r\nimport { ConfirmationOverlayContextProvider } from './app/common-page-components/confirmation-overlay/ConfirmationOverlayContext';\r\nimport { BTContextMenuContextProvider } from './app/common-page-components/context-menu/BTContextMenuContext';\r\nimport EEBalloons from './app/common-page-components/ee/balloons/EEBalloons';\r\nimport FloatingLoadingIndicator from './app/common-page-components/floating-loading-indicator/FloatingLoadingIndicator';\r\nimport { FloatingLoadingIndicatorContextProvider } from './app/common-page-components/floating-loading-indicator/FloatingLoadingIndicatorContext';\r\nimport { BTGeneralContextProvider } from './app/common-page-components/general-contexts/BTGeneralContext';\r\nimport LoadingPageOverlay from './app/common-page-components/loading-page-overlay/LoadingPageOverlay';\r\nimport { LoadingPageOverlayContextProvider } from './app/common-page-components/loading-page-overlay/LoadingPageOverlayContext';\r\nimport MobileDeviceOverlay from './app/common-page-components/mobile-device-overlay/MobileDeviceOverlay';\r\nimport { BTModalContextProvider } from './app/common-page-components/modal/BTModalContext';\r\nimport NotificationPanel from './app/common-page-components/notification-panel/NotificationPanel';\r\nimport { NotificationPanelContextProvider } from './app/common-page-components/notification-panel/NotificationPanelContext';\r\nimport BTPopover from './app/common-page-components/popover/BTPopover';\r\nimport { BTPopoverContextProvider } from './app/common-page-components/popover/BTPopoverContext';\r\nimport ReloadAppTimer from './app/common-page-components/reload-app-timer/ReloadAppTimer';\r\nimport SupportOverlay from './app/common-page-components/support-overlay/SupportOverlay';\r\nimport { SupportOverlayContextProvider } from './app/common-page-components/support-overlay/SupportOverlayContext';\r\nimport { FeatureFlagContextProvider } from './app/feature-flagging/FeatureFlagContext';\r\nimport './internationalization/setup';\r\nimport * as serviceWorker from './registerServiceWorker';\r\nimport { DispatchManagerContextProvider } from './services/dispatch-manager/DispatchManager';\r\nimport { initializeAppInsights } from './services/logger/AppInsights';\r\nimport { LoggingContextProvider } from './services/logger/Logger';\r\nimport { getConfig } from './utils/config';\r\n\r\nconst baseUrl = document.getElementsByTagName('base')[0].getAttribute('href') || '/';\r\nconst rootElement = document.getElementById('root');\r\n\r\nconst instrumentationKey = getConfig('REACT_APP_APPINSIGHTS_INSTRUMENTATIONKEY');\r\nconst browserHistory = createBrowserHistory({ basename: baseUrl });\r\nconst appInsightsPlugin = initializeAppInsights(instrumentationKey, browserHistory);\r\n\r\nReactDOM.render(\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ,\r\n\r\n rootElement,\r\n);\r\n\r\n// If you want your app to work offline and load faster, you can change\r\n// unregister() to register() below. Note this comes with some pitfalls.\r\n// Learn more about service workers: https://bit.ly/CRA-PWA\r\nserviceWorker.unregister();\r\n","import {\n ApplicationInsights,\n DistributedTracingModes,\n Util,\n} from '@microsoft/applicationinsights-web';\nimport { ReactPlugin } from '@microsoft/applicationinsights-react-js';\nimport { History } from 'history';\n\n// Initializes the app insights react plugin\nexport const initializeAppInsights = (\n instrumentationKey: string | undefined,\n browserHistory: History,\n): ReactPlugin | undefined => {\n if (!instrumentationKey) {\n return undefined;\n }\n\n const reactPlugin = new ReactPlugin();\n\n const appInsights = new ApplicationInsights({\n config: {\n instrumentationKey: instrumentationKey,\n distributedTracingMode: DistributedTracingModes.W3C,\n enableCorsCorrelation: true,\n enableAutoRouteTracking: true,\n extensions: [reactPlugin],\n extensionConfig: {\n [reactPlugin.identifier]: { history: browserHistory },\n },\n },\n });\n\n appInsights.loadAppInsights();\n\n // Set cloud roles -- must be done after loadAppInsights call\n appInsights.addTelemetryInitializer((envelope) => {\n if (envelope.tags === undefined) {\n envelope.tags = [];\n }\n\n envelope.tags.push({ 'ai.cloud.role': 'Website' });\n envelope.tags.push({ 'ai.cloud.roleInstance': 'Website' });\n });\n\n // Use a new traceId for each request -- must be done after loadAppInsights call\n // NOTE: By default the same traceId is used per page, which makes it hard to\n // correlate logs for a single request\n appInsights.addDependencyListener((details) => {\n details.traceId = Util.generateW3CId();\n });\n\n return reactPlugin;\n};\n"],"sourceRoot":""}