{"version":3,"file":"index.acbee6dc.js","sources":["../../../src/i18n.js","../../../src/api/constants.ts","../../../src/api/client/client.ts","../../../src/api/profile/current-user.ts","../../../src/context/Auth.tsx","../../../src/api/apps/apps.ts","../../../src/assets/images/logo-be-awere-stay-safe.svg","../../../src/assets/images/logo-light-blue.svg","../../../src/assets/images/rocket-with-line.png","../../../src/theme/palette.ts","../../../src/theme/components/MuiAlert.tsx","../../../src/theme/typography.ts","../../../src/theme/components/MuiButton.ts","../../../src/theme/components/MuiCheckbox.ts","../../../src/theme/components/MuiChip.ts","../../../src/theme/components/MuiIconButton.ts","../../../src/theme/components/MuiMenuItem.ts","../../../src/theme/components/MuiPaper.ts","../../../src/theme/components/MuiRadio.ts","../../../src/theme/components/MuiTab.ts","../../../src/theme/components/MuiTable.ts","../../../src/assets/images/switch/locked-light.svg","../../../src/theme/components/MuiSwitch.ts","../../../src/theme/components/MuiCard.ts","../../../src/theme/components/MuiMenu.ts","../../../src/theme/components/MuiButtonGroup.ts","../../../src/theme/components/index.ts","../../../src/theme/theme.ts","../../../src/common/components/Integrations/MicrosoftEntraIdInstructions.tsx","../../../src/assets/images/logo-clean-blue.svg","../../../src/common/hooks/useNavigateWithLayoutBlocker.tsx","../../../src/common/components/Alert/Alert.tsx","../../../src/api/alerts/read-alert.ts","../../../src/common/hooks/useToast.tsx","../../../src/common/components/Navbar/AlertPanel/Alert.tsx","../../../src/api/alerts/alerts.ts","../../../src/api/alerts/read-all-alerts.ts","../../../src/common/components/Navbar/AlertPanel/AlertPanel.tsx","../../../src/api/auth/logout.ts","../../../src/common/hooks/useLottie.tsx","../../../src/common/animations/NewLabelAnimation.tsx","../../../src/common/utils/sanitizeString.ts","../../../src/types/organizations.ts","../../../src/common/components/TruncatedText/TruncatedText.tsx","../../../src/common/components/Navbar/Dropdown.tsx","../../../src/common/components/Layout/MenuItem.tsx","../../../src/common/components/Layout/Menu.tsx","../../../src/api/utils/serialize-array.ts","../../../src/api/domains/get.ts","../../../src/types/common.ts","../../../src/types/domains.ts","../../../src/common/components/QuickActions/QuickActions.tsx","../../../src/common/components/Layout/Layout.tsx","../../../src/common/utils/app-utils.tsx","../../../src/context/ContentLibraryContext/ContentLibraryContext.tsx","../../../src/api/organizations/get.ts","../../../src/common/components/Inputs/Checkbox/index.tsx","../../../src/common/components/Inputs/TextField/index.tsx","../../../src/api/organizations/create.ts","../../../src/api/utils/get-error.ts","../../../src/common/components/Modal/index.tsx","../../../src/assets/images/account-center/invite-image.svg","../../../src/common/components/AccountCenter/PopupsStyledComponents.tsx","../../../src/common/components/AccountCenter/InvitePopup.tsx","../../../src/common/components/AccountCenter/ModalStyledComponents.tsx","../../../src/common/components/AccountCenter/AddModal.tsx","../../../src/api/organizations/update.ts","../../../src/assets/images/popup/question.svg","../../../src/common/components/Popup/index.tsx","../../../src/common/components/AccountCenter/ArchivePopup.tsx","../../../src/api/profile/switch-client.ts","../../../src/assets/images/account-center/no-permissions.svg","../../../src/assets/images/account-center/switch-account.svg","../../../src/common/components/AccountCenter/ClientSwitchPopup.tsx","../../../src/common/components/MobilePhonePreview/LoadingAnimation.tsx","../../../src/common/components/AccountCenter/EditModal.tsx","../../../src/common/components/AccountCenter/TreeChartSearch.tsx","../../../src/common/components/AccountCenter/TreeChartActions.tsx","../../../src/assets/images/account-center-icons/add-hover.svg","../../../src/assets/images/account-center-icons/add.svg","../../../src/common/components/AccountCenter/TreeChartCard.tsx","../../../src/common/components/AccountCenter/TreeChart.tsx","../../../src/pages/AccountCenter/index.tsx","../../../src/pages/Auth/ArchivedOrganiztionPage/index.tsx","../../../src/assets/images/smart-city.gif","../../../src/common/components/Layout/FutureFormWrapper.tsx","../../../src/api/auth/mfa-setup.ts","../../../src/api/auth/mfa-verify.ts","../../../src/common/utils/detectAutofill-utils.ts","../../../src/common/components/Inputs/HelperTextComponent.tsx","../../../src/common/components/Inputs/TextFieldV2/index.tsx","../../../src/pages/Auth/MFASetup/App.tsx","../../../src/pages/Auth/MFASetup/ChooseType.tsx","../../../src/common/utils/time.ts","../../../src/common/components/EmailResend/index.tsx","../../../src/pages/Auth/MFASetup/Email.tsx","../../../src/pages/Auth/MFASetup/index.tsx","../../../src/api/auth/request-password-reset.ts","../../../src/pages/Auth/ResetPassword/ResetPasswordEmail.tsx","../../../src/api/auth/verify-password-reset-token.ts","../../../src/pages/Auth/ResetPassword/VerifyResetToken.tsx","../../../src/api/auth/reset-password.ts","../../../src/pages/Settings/Admins/PasswordStrengthEvaluation.tsx","../../../src/common/components/Inputs/PasswordField/index.tsx","../../../src/pages/Auth/ResetPassword/SetPassword.tsx","../../../src/assets/images/auth/success.svg","../../../src/pages/Auth/ResetPassword/ResetPasswordSuccess.tsx","../../../src/pages/Auth/ResetPassword/index.tsx","../../../src/api/auth/signup.ts","../../../src/api/terms/get.ts","../../../src/common/components/Inputs/PhoneNumberField/index.tsx","../../../src/pages/Auth/SignUpPage/SignUpForm.tsx","../../../src/pages/Auth/SignUpPage/SignUpSuccess.tsx","../../../src/pages/Auth/SignUpPage/index.tsx","../../../src/api/auth/login.ts","../../../src/pages/Auth/SingIn/Login.tsx","../../../src/pages/Auth/SingIn/MFA.tsx","../../../src/assets/images/auth/locked_bouncer.svg","../../../src/pages/Auth/UserLocked.tsx","../../../src/pages/Auth/SingIn/index.tsx","../../../src/api/auth/unlock-user.ts","../../../src/assets/images/auth/unlocked_bouncer.svg","../../../src/common/hooks/useUrlQuery.ts","../../../src/pages/Auth/UserUnlockedPage.tsx","../../../src/api/auth/activate-account.ts","../../../src/pages/Auth/VerifyEmail.tsx","../../../src/api/campaigns/campaign-assets.ts","../../../src/api/campaigns/campaign-report.ts","../../../src/api/campaigns/get.ts","../../../src/api/campaigns/getUsers.ts","../../../src/api/groups/get.ts","../../../src/common/animations/FeedbackAnimation.tsx","../../../src/common/components/CampaignDetails/CampaignDetails.tsx","../../../src/common/hooks/useInterval.ts","../../../src/types/campaigns.ts","../../../src/common/components/Countdown/Countdown.tsx","../../../src/common/components/NoResultsContainer/NoResultsContainer.tsx","../../../src/common/components/InfoTooltip/InfoTooltip.tsx","../../../src/common/components/GaugeScoremeter/GaugeScoremeter.tsx","../../../src/common/components/LoadingContainer/LoadingContainer.tsx","../../../src/types/phishingSimulations.ts","../../../src/common/components/DeviceFrame/DeviceFrame.tsx","../../../src/assets/images/MobilePreview/WhatsAppPreview/WhatsAppSender.svg","../../../src/assets/images/MobilePreview/WhatsAppPreview/WhatsAppBottom.svg","../../../src/assets/images/MobilePreview/WhatsAppPreview/WhatsAppToday.svg","../../../src/assets/images/MobilePreview/WhatsAppPreview/WhatsAppBackGround.png","../../../src/common/components/MobilePhonePreview/StatusBar.tsx","../../../src/common/components/MobilePhonePreview/WhatsAppPreview.tsx","../../../src/assets/images/MobilePreview/SmsPreviewApp/SmsTop.svg","../../../src/assets/images/MobilePreview/SmsPreviewApp/SmsBottom.svg","../../../src/assets/images/MobilePreview/SmsPreviewApp/SmsMessageTip.svg","../../../src/assets/images/MobilePreview/SmsPreviewApp/hook-background.gif","../../../src/common/components/MobilePhonePreview/SmsAppPreview.tsx","../../../src/assets/images/MobilePreview/mobileFrontFrame.png","../../../src/common/components/MobilePhonePreview/index.tsx","../../../src/common/utils/isLanguageRTL.ts","../../../src/common/components/SimulationPreview/SimulationPreview.tsx","../../../src/assets/images/too-fast.png","../../../src/pages/TrainingCampaignDashboard/ReportAlert.tsx","../../../src/pages/CampaignDashboard/CampaignGroupAnalytics.tsx","../../../src/common/components/HumanizedScore/HumanizedScore.tsx","../../../src/common/components/Tables/IndeterminateCheckbox.tsx","../../../src/common/components/Tables/MultiselectBar.tsx","../../../src/common/components/Tables/TablePaginationActions.tsx","../../../src/common/components/Tables/PaginatingTable.tsx","../../../src/common/components/Tags/Tags.tsx","../../../src/pages/CampaignDashboard/CampaignUsersTable.tsx","../../../src/common/components/Tables/EditableCell.tsx","../../../src/api/terms/post.ts","../../../src/context/TermsContext.tsx","../../../src/assets/images/popup/terms-modal.svg","../../../src/Routes/ProtectedRoute.tsx","../../../src/common/utils/tab-utils.ts","../../../src/assets/images/coming-soon.svg","../../../src/common/components/ComingSoon/ComingSoon.tsx","../../../src/pages/ContentLibrary/NewslettersLibrary/NewslettersLibrary.tsx","../../../src/api/education-modules/recommended-modules.ts","../../../src/api/categories/categories.ts","../../../src/api/education-modules/delete-module.ts","../../../src/api/education-modules/modules.ts","../../../src/api/profile/toggle-saved-asset.ts","../../../src/api/campaigns/create.ts","../../../src/api/offices/get.ts","../../../src/assets/images/popup/score-max.svg","../../../src/assets/images/cywareness_default.png","../../../src/common/config.ts","../../../src/api/phishing-simulations/get.ts","../../../src/assets/images/popup/remove.svg","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPackageMenu/SimulationPackageCard.tsx","../../../src/assets/images/simulation-packages/all-cover.svg","../../../src/assets/images/simulation-packages/email-cover.svg","../../../src/assets/images/simulation-packages/sms-cover.svg","../../../src/assets/images/simulation-packages/whatsapp-cover.svg","../../../src/assets/images/simulation-packages/email-sms-cover.svg","../../../src/assets/images/simulation-packages/sms-whatsapp-cover.svg","../../../src/assets/images/simulation-packages/email-whatsapp-cover.svg","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPackageMenu/SimulationPackageCardUtils.ts","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPackageMenu/SimulationPackagePreview.tsx","../../../src/common/components/LaunchWizard/AdvancedSettings.tsx","../../../src/common/components/LaunchWizard/StepperIcon.tsx","../../../src/common/components/Tabs/MainTab.tsx","../../../src/common/components/Tabs/MainTabPage.tsx","../../../src/common/components/Tabs/MainTabs.tsx","../../../src/common/components/Tabs/MainTabsWrapper.tsx","../../../src/api/dynamic-groups/get.ts","../../../src/common/hooks/useQueryParams.tsx","../../../src/common/components/SimpleSearchBar/SimpleSearchBar.tsx","../../../src/common/components/Table/TableFooter.tsx","../../../src/common/components/Table/TableHead.tsx","../../../src/common/components/Table/TableNoResults.tsx","../../../src/common/components/Table/TableSceletonLoader.tsx","../../../src/common/components/Table/index.tsx","../../../src/common/components/Tables/NoResults.tsx","../../../src/common/components/LaunchWizard/DistibutionSelect.tsx","../../../src/common/components/LaunchWizard/LaunchWizardDynamicGroupsTable.tsx","../../../src/common/components/StatusFilter/StatusFilter.tsx","../../../src/common/components/Tables/InTableMessageWithAnimation.tsx","../../../src/common/components/LaunchWizard/LaunchWizardGroupsTable.tsx","../../../src/assets/locales/languages.ts","../../../src/common/components/LaunchWizard/LaunchWizardOfficesTable.tsx","../../../src/api/members/get.ts","../../../src/common/components/Table/CellComponents/GroupCellComponent.tsx","../../../src/common/components/Table/CellComponents/OfficeCellComponent.tsx","../../../src/common/components/LaunchWizard/LaunchWizardUsersTable.tsx","../../../src/api/dynamic-groups/getMembers.ts","../../../src/common/components/LaunchWizard/UserPicker.tsx","../../../src/common/components/LaunchWizard/CampaignDetails.tsx","../../../src/common/components/LaunchWizard/LaunchWizard.tsx","../../../src/api/upload/upload.ts","../../../src/common/components/FileUpload/FileUpload.tsx","../../../src/common/components/Form/Form.tsx","../../../src/api/education-modules/create-module.ts","../../../src/api/education-modules/edit-module.ts","../../../src/assets/images/upload-video.svg","../../../src/api/upload/upload-cloudinary-direct.ts","../../../src/pages/ContentLibrary/VideosLibrary/CreateVideoModal/VideoUpload.tsx","../../../src/pages/ContentLibrary/VideosLibrary/CreateVideoModal/ThumbnailCapture.tsx","../../../src/pages/ContentLibrary/VideosLibrary/CreateVideoModal/utils/generateSubtitleTracksObject.ts","../../../src/common/components/TagsFilter/TagsFilter.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoTagsFilter.tsx","../../../src/common/components/VideoPlayerV2/CustomPlayButton.tsx","../../../src/common/components/VideoPlayerV2/SourceSelector.tsx","../../../src/common/components/VideoPlayerV2/VideoPlayerV2.tsx","../../../src/common/components/Form/useForm.ts","../../../src/pages/ContentLibrary/VideosLibrary/CreateVideoModal/CreateVideoModal.tsx","../../../src/common/components/Carousel/Carousel.tsx","../../../src/common/utils/cloudinary-utils.ts","../../../src/common/utils/secondsToTimestamp.ts","../../../src/common/utils/shortenString.ts","../../../src/pages/ContentLibrary/VideosLibrary/VideoCard.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoLibraryCardView.tsx","../../../src/api/videos/get.ts","../../../src/common/components/Table/CellComponents/LibraryTitleCellComponent.tsx","../../../src/common/components/Table/CellComponents/VideoLibraryActionsCellComponent.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoLibraryTable.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoPreviewModal.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideosLibrary.tsx","../../../src/common/components/DifficultyFilter/DifficultyFilter.tsx","../../../src/common/components/VectorFilter/VectorFilter.tsx","../../../src/context/ContentLibraryContext/useContentLibrary.ts","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationCard.tsx","../../../src/api/phishing-simulations/packages/create.ts","../../../src/api/phishing-simulations/packages/update.ts","../../../src/assets/images/popup/stop.svg","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPackageMenu/DroppablePackageCard.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPackageMenu/index.tsx","../../../src/common/components/LanguageFilter/LanguageFilter.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationsLanguagesFilter.tsx","../../../src/api/phishing-simulations/packages/delete.ts","../../../src/assets/images/popup/delete.svg","../../../src/pages/ContentLibrary/SimulationsLibrary/DeletePackagePopup.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPackageMenu/SimulationPackageCarouselCard.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/PackagesCaruselView.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationLibraryCardView.tsx","../../../src/common/components/Table/CellComponents/SimulationLibraryActionsCellComponent.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationLibraryTable.tsx","../../../src/api/phishing-simulations/delete.ts","../../../src/api/phishing-simulations/packages/get.ts","../../../src/api/profile/toggle-saved-asset-package.ts","../../../src/pages/ContentLibrary/SimulationsLibrary/DeleteSimulationPopup.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationsLibrary.tsx","../../../src/common/components/TagsFilter/TagsFilterNew.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationsTagsFilter.tsx","../../../src/api/education-modules/languages.ts","../../../src/pages/ContentLibrary/VideosLibrary/VideoLanguagesFilter.tsx","../../../src/common/components/Layout/LayoutPageContent/index.tsx","../../../src/common/components/Breadcrumbs/Breadcrumbs.tsx","../../../src/common/components/Layout/LayoutPageContent/PageHeader.tsx","../../../src/pages/ContentLibrary/ContentLibrary.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/DraggedSimualtionTableRow.tsx","../../../src/common/components/Tables/SimpleTable.tsx","../../../src/common/utils/numberWithCommas.ts","../../../src/pages/CampaignDashboard/ShieldWithMagnifyingGlassIcon.tsx","../../../src/pages/CampaignDashboard/DataBasePlusIcon.tsx","../../../src/pages/CampaignDashboard/EventsStepper.tsx","../../../src/pages/CampaignDashboard/MultiSimPreviewTabs.tsx","../../../src/pages/CampaignDashboard/index.tsx","../../../src/api/campaigns/cancel.ts","../../../src/api/campaigns/edit.ts","../../../src/api/education-modules/module-by-id.ts","../../../src/common/components/PopupLarge/index.tsx","../../../src/common/components/Campaign/EditModal.tsx","../../../src/common/components/InfoTooltip/TimezoneTooltip.tsx","../../../src/common/components/MoreMenu/MoreMenu.tsx","../../../src/common/components/Table/TableCellCampaignType.tsx","../../../src/pages/Campaigns/CampaignDateRangePicker/CampaignDateRangePicker.tsx","../../../src/pages/Campaigns/Campaigns.tsx","../../../src/api/client-activity/client-activity.ts","../../../src/common/components/Tables/DateFilter.tsx","../../../src/common/utils/table-size.ts","../../../src/pages/ClientActivity/ClientActivityTable.tsx","../../../src/pages/ClientActivity/ClientActivityDashboard.tsx","../../../src/common/hooks/useLocalStorage.ts","../../../src/common/components/Particles/CustomParticles.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/email/Types.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/email/Reducers.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/email/Actions.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/wizard/Types.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/wizard/Reducers.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/wizard/Actions.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/landing-page/Types.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/landing-page/Reducers.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/landing-page/Actions.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/summary-page/Types.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/summary-page/Reducers.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/summary-page/Actions.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/state/Context.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/AiWizard.tsx","../../../src/api/open-ai/openai-request.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/LanguageSelect.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/constants/tone-of-voice.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/ToneOfVoiceSelect.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/AiHint.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/EmailBody.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/Instructions.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/AppDesignSelection.tsx","../../../src/api/brands/brands.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/AppNameSelection.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/constants/micro-training.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/DifficultyLevelSelector.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/PersonalizeTemplateToggle.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/AdvancedTemplateSettings.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/AILinkToLogo.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/AiForms/AppEmailForm.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/SenderName.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/constants/sender-position.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/SenderPosition.tsx","../../../src/common/components/UploadImageModal/ImageUploadComponent.tsx","../../../src/common/components/UploadImageModal/UploadImageModal.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/EmailSenderSignature.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/AiForms/HumanEmailForm.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/AiLoader.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/EmailPlaceholder.tsx","../../../src/assets/images/PC-Simulation/pc-screen.png","../../../src/assets/images/PC-Simulation/hook-background.gif","../../../src/assets/images/PC-Simulation/cywail-logo.svg","../../../src/assets/images/PC-Simulation/cymagnify-logo.svg","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/MonitorPreview.tsx","../../../src/common/animations/NewBadgeAnimation.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/VectorToggleButtons.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/constants/loading-phrases.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/utils/createEmailBodyPrompt.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/utils/createEmailSubjectPrompt.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/utils/createSMSBodyPrompt.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/utils/createSMSSubjectPrompt.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/utils/createWhatsAppBodyPrompt.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/MonitorPreviewIframe.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/EmailBuilder.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/IntroScreen.tsx","../../../src/assets/images/MobilePreview/LandingPagePreview/Bottom.svg","../../../src/common/components/MobilePhonePreview/BrowserAppPreview.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/LandingPageInstructions.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/LandingPageTypeSelection.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/SimulationTypePreview.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/utils/createLandingPagePrompt.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/LandingPageBuilder.tsx","../../../src/api/phishing-simulations/create.ts","../../../src/assets/images/MobilePreview/MicroTrainingPreview/MicroTrainingScreen.png","../../../src/assets/images/Micro-Training/micro.png","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/MicroTrainingOutput.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/SummaryTabs.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/components/SummaryTitle.tsx","../../../src/assets/locales/utils.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/utils/generateScreenshots.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/utils/templateTransformers.ts","../../../src/pages/ContentLibrary/AiSimulationBuilder/SummaryPage.tsx","../../../src/pages/ContentLibrary/AiSimulationBuilder/AiSimulationBuilder.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPage/SimulationPagePreviews.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPage/SimulationPageStats.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPage/SimulationPageTopics.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPackagePage/index.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPage/SimulationPageActions.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPage/SimulationPageDetails.tsx","../../../src/pages/ContentLibrary/SimulationsLibrary/SimulationPage/SimulationPage.tsx","../../../src/pages/ContentLibrary/VideosLibrary/CreateVideoPage/VideoUploadComponent.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoEditableContent.tsx","../../../src/pages/ContentLibrary/VideosLibrary/CreateVideoPage/CreateVideoPage.tsx","../../../src/pages/ContentLibrary/VideosLibrary/EditVideoPage/EditVideoPage.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoPage/VideoPageActions.tsx","../../../src/common/components/EmbeddedContent/EmbeddedContent.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoPage/VideoPageQuizzesLink.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoPage/VideoPageContentLink.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoPage/VideoPageTopics.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoPage/VideoPageDetails.tsx","../../../src/pages/ContentLibrary/VideosLibrary/VideoPage/VideoPage.tsx","../../../src/api/admin-analytics/admin-analytics.ts","../../../src/api/dashboard-analytics.ts","../../../src/assets/images/flat-smiley.svg","../../../src/common/components/AwarenessScore/AwarenessScore.tsx","../../../src/api/banners/get.ts","../../../src/pages/ContentLibrary/SimulationsLibrary/BannerCarousel.tsx","../../../src/common/components/SliderDots/Dots.tsx","../../../src/common/utils/difficultyToColor.ts","../../../src/pages/Dashboard/DepartmentScores.tsx","../../../src/api/reports/reports-analytics.ts","../../../src/pages/Dashboard/PendingAlerts.tsx","../../../src/pages/Dashboard/UpcomingCampaigns.tsx","../../../src/pages/Dashboard/Dashboard.tsx","../../../src/common/components/Card/CardHeader.tsx","../../../src/pages/DynamicGroupProfile/index.tsx","../../../src/assets/images/ExpiredCampaign/simulation_door.svg","../../../src/common/hooks/useDeviceDetection.ts","../../../src/pages/ExpiredCampagin/ExpiredCampaign.tsx","../../../src/pages/TrainingCampaignView/InvalidToken.tsx","../../../src/common/utils/language-utils.ts","../../../src/assets/images/logo-blue.svg","../../../src/pages/Genesis/TrainingCampaignDemoTour.tsx","../../../src/pages/Genesis/TrainingCampaignDemoViewHeader.tsx","../../../src/assets/images/megaphone.png","../../../src/pages/TrainingCampaignView/UnfinishedAlert.tsx","../../../src/pages/Genesis/TrainingCampaignDemoView.tsx","../../../src/api/group/delete.ts","../../../src/api/group/get.ts","../../../src/api/group/remove-members.ts","../../../src/api/group/add-members.ts","../../../src/api/group/edit.ts","../../../src/pages/GroupProfile/EditGroupModal.tsx","../../../src/pages/GroupProfile/index.tsx","../../../src/api/campaigns/getMicrotraining.ts","../../../src/api/events/log.ts","../../../src/assets/images/logo-dark.svg","../../../src/common/hooks/useLogEvent.ts","../../../src/assets/images/DesktopPreview/email-frame.svg","../../../src/common/components/DesktopPreview/EmailMessage.tsx","../../../src/assets/images/DesktopPreview/whatsapp-frame.svg","../../../src/assets/images/DesktopPreview/today-business-tags.svg","../../../src/common/components/DesktopPreview/WhatsAppMessage.tsx","../../../src/assets/images/MobilePreview/EmailAppPreview/gmail-frame.svg","../../../src/common/components/MobilePhonePreview/EmailAppPreview.tsx","../../../src/pages/Microtraining/components/DevicePreview.tsx","../../../src/pages/Microtraining/components/Header.tsx","../../../src/pages/Microtraining/components/InvalidToken.tsx","../../../src/pages/Microtraining/index.tsx","../../../src/api/office/edit.ts","../../../src/api/office/get.ts","../../../src/assets/countries.ts","../../../src/assets/usStates.ts","../../../src/common/components/CreateOfficeModal/CreateOfficeModal.tsx","../../../src/common/components/ScoreMeter/SvgGradient.tsx","../../../src/common/components/UserPerformanceChart/UserPerformanceChart.tsx","../../../src/pages/OfficeProfile/OfficeUsersTable.tsx","../../../src/common/components/Tables/Filter.tsx","../../../src/pages/OfficeProfile/OfficeGroupsTable.tsx","../../../src/pages/OfficeProfile/OfficeTables.tsx","../../../src/pages/OfficeProfile/index.tsx","../../../src/api/organizations/getStatus.ts","../../../src/api/domains/sendInstructions.ts","../../../src/api/domains/update.ts","../../../src/api/domains/verifyConfig.ts","../../../src/assets/images/Integrations/Types/AdGoogleWorkspace.svg","../../../src/assets/images/Integrations/Types/AdOnPremise.svg","../../../src/assets/images/Integrations/Types/Office365.svg","../../../src/assets/images/popup/domain.svg","../../../src/common/components/Form/TwoColumnsLayout.tsx","../../../src/common/components/InfoAlert/InfoAlert.tsx","../../../src/common/components/Inputs/RadioGroup/index.tsx","../../../src/common/components/Inputs/Select/index.tsx","../../../src/common/components/Allowlisting/AllowlistingTooltips.tsx","../../../src/common/components/Allowlisting/index.tsx","../../../src/common/components/Layout/LayoutPageContent/LayoutAccordion.tsx","../../../src/pages/Onboarding/components/Styled.tsx","../../../src/pages/Onboarding/components/AllowlistingStep.tsx","../../../src/api/domains/create.ts","../../../src/api/domains/delete.ts","../../../src/api/domains/verifyTXTRecord.ts","../../../src/common/components/DomainsTable/index.tsx","../../../src/pages/Onboarding/components/DomainVerificationStep.tsx","../../../src/assets/images/progress-component/icon-background-complete.svg","../../../src/assets/images/progress-component/icon-background.svg","../../../src/common/components/StepsProgress/Step.tsx","../../../src/common/components/StepsProgress/StepTransition.tsx","../../../src/common/components/StepsProgress/index.tsx","../../../src/pages/Onboarding/components/OnboardingProgress.tsx","../../../src/api/client/update-client.ts","../../../src/api/organizations/getIndustries.ts","../../../src/common/components/Inputs/CountrySelect/index.tsx","../../../src/common/components/UploadImageBox/UploadImageBox.tsx","../../../src/pages/Onboarding/components/OrganizationDetailsStep.tsx","../../../src/api/integrations/integrations.ts","../../../src/api/office/create.ts","../../../src/assets/images/popup/complete.gif","../../../src/api/members/upload.ts","../../../src/common/components/Inputs/InputFile/index.tsx","../../../src/common/components/Stepper/StepConnector.tsx","../../../src/common/components/Stepper/index.tsx","../../../src/common/components/Stepper/StepIcon.tsx","../../../src/common/components/Stepper/Step.tsx","../../../src/common/components/BulkUserUploadModal/StepSubmit.tsx","../../../src/common/components/BulkUserUploadModal/Step1.tsx","../../../src/common/components/BulkUserUploadModal/UploadLoading.tsx","../../../src/common/components/BulkUserUploadModal/Step2.tsx","../../../src/types/members.ts","../../../src/common/components/BulkUserUploadModal/ConflictMemberCard.tsx","../../../src/common/components/BulkUserUploadModal/Step3.tsx","../../../src/common/components/BulkUserUploadModal/Step4.tsx","../../../src/common/components/BulkUserUploadModal/Step5.tsx","../../../src/assets/images/upload-file.svg","../../../src/common/components/BulkUserUploadModal/Step6.tsx","../../../src/common/components/BulkUserUploadModal/index.tsx","../../../src/common/components/CenteredPopup/index.tsx","../../../src/api/group/create.ts","../../../src/common/components/CreateGroupModal/CreateGroupModal.tsx","../../../src/api/member/create.ts","../../../src/api/member/edit.ts","../../../src/common/components/CreateUserModal/CreateUserModal.tsx","../../../src/api/integrations/create.ts","../../../src/api/integrations/entities.ts","../../../src/api/integrations/test-connection.ts","../../../src/api/integrations/update.ts","../../../src/assets/images/Integrations/FormStages/IdCard.svg","../../../src/assets/images/Integrations/FormStages/Tools.svg","../../../src/common/components/Inputs/Autocomplete/index.tsx","../../../src/common/components/Inputs/Timepicker/index.tsx","../../../src/types/integrations.ts","../../../src/common/components/Integrations/InactiveUsersModal.tsx","../../../src/assets/images/Integrations/Types/AdAzure.svg","../../../src/common/components/Integrations/IntegrationsUtils.ts","../../../src/common/components/Integrations/MicrosoftEntraIdIntegration.tsx","../../../src/common/components/Integrations/DepartmentMapper.tsx","../../../src/common/components/Integrations/OnPremiseIntegration.tsx","../../../src/api/integrations/authenticate-to-gws.ts","../../../src/common/components/Integrations/GoogleWorkspaceIntegration.tsx","../../../src/common/components/Integrations/IntegrationPicker.tsx","../../../src/assets/images/Integrations/FormStages/Disks.svg","../../../src/common/components/Integrations/IntegrationModal.tsx","../../../src/pages/Onboarding/components/RecipientMangementStep.tsx","../../../src/pages/Onboarding/NewOnboarding.tsx","../../../src/pages/PricingCalculator/components/StyledTextField.tsx","../../../src/pages/PricingCalculator/components/CampaignsCountField.tsx","../../../src/assets/images/cywareness-calculator-logo.svg","../../../src/pages/PricingCalculator/components/Header.tsx","../../../src/pages/PricingCalculator/components/MainAccordion.tsx","../../../src/pages/PricingCalculator/components/MainPlanCard.tsx","../../../src/pages/PricingCalculator/components/utils.ts","../../../src/pages/PricingCalculator/components/MainTable/CellContent.tsx","../../../src/pages/PricingCalculator/components/MainTable/TableSection.tsx","../../../src/pages/PricingCalculator/components/MainTable/index.tsx","../../../src/pages/PricingCalculator/components/MembersCountFiels.tsx","../../../src/pages/PricingCalculator/components/PlanPicker/PlanPickerCardSection.tsx","../../../src/pages/PricingCalculator/components/PlanPicker/PickerPlanCard.tsx","../../../src/pages/PricingCalculator/components/PlanPicker/index.tsx","../../../src/pages/PricingCalculator/components/Summary.tsx","../../../src/pages/PricingCalculator/index.tsx","../../../src/api/training-campaigns/training-by-token.ts","../../../src/common/utils/intToChar.ts","../../../src/pages/Quiz/Answer.tsx","../../../src/api/quizzes/check-answer.ts","../../../src/api/quizzes/Summary.tsx","../../../src/pages/Quiz/LanguageSelect.tsx","../../../src/api/quizzes/quiz-by-id.tsx","../../../src/pages/Quiz/Quiz.tsx","../../../src/common/components/CircularProgressWithLabel/CircularProgressWithLabel.tsx","../../../src/pages/ResponseConsole/ReportsChart.tsx","../../../src/pages/ResponseConsole/ReportsAnalytics.tsx","../../../src/api/reports/reports.ts","../../../src/pages/ResponseConsole/ReportsTable.tsx","../../../src/pages/ResponseConsole/ResponseConsole.tsx","../../../src/common/components/Calendar/Calendar.tsx","../../../src/pages/ResponseConsoleReport/ReportCalendar.tsx","../../../src/pages/ResponseConsoleReport/ReportDetails.tsx","../../../src/common/components/CodeEditor/CodeEditor.tsx","../../../src/common/utils/htmlHandler.ts","../../../src/pages/ResponseConsoleReport/ReportFindings.tsx","../../../src/pages/ResponseConsoleReport/ReportHeaders.tsx","../../../src/pages/ResponseConsoleReport/ResponseConsoleReport.tsx","../../../src/api/auth/accept-invitation.ts","../../../src/api/auth/verify-token.ts","../../../src/assets/images/popup/desk.svg","../../../src/pages/Settings/Admins/AcceptInvitationPage.tsx","../../../src/api/admins/get.ts","../../../src/api/admins/disable-admin.ts","../../../src/api/admins/edit-role.ts","../../../src/api/admins/enable-admin.ts","../../../src/api/profile/edit.ts","../../../src/types/admins.ts","../../../src/pages/Settings/Admins/AdminStatusPopup.tsx","../../../src/api/profile/edit-email-confirm.ts","../../../src/pages/Settings/Admins/EmailConfirmModal.tsx","../../../src/pages/Settings/Admins/AdminProfile/AdminProfileDetailsSection.tsx","../../../src/common/components/Card/CardSummeryIcon.tsx","../../../src/pages/Settings/Admins/AdminProfile/AdminProfileSummary.tsx","../../../src/api/admins/disable-mfa.ts","../../../src/pages/Settings/Admins/AdminProfile/AdminProfileMFA.tsx","../../../src/api/profile/edit-change-password.ts","../../../src/pages/Settings/Admins/AdminProfile/AdminProfileSecuritySection.tsx","../../../src/assets/images/admin-profile/another_planet.svg","../../../src/pages/Settings/Admins/AdminProfile/SupportAdminSwitchAccount.tsx","../../../src/pages/Settings/Admins/AdminProfile/index.tsx","../../../src/api/admins/remove-admin.ts","../../../src/api/admins/resend-invite.ts","../../../src/pages/Settings/Admins/AdminsTable.tsx","../../../src/api/admins/invite-admin.ts","../../../src/pages/Settings/Admins/InviteAdminModal.tsx","../../../src/assets/images/SettingsPage/SettingsPageImage.svg","../../../src/pages/Settings/Configurations/ConfigurationsStyledComponents.tsx","../../../src/pages/Settings/Configurations/OrganizationCapacityBar.tsx","../../../src/pages/Settings/Configurations/OrganizationSettings.tsx","../../../src/api/profile/redeem-promo-code.ts","../../../src/pages/Settings/Configurations/RedeemPromoCode.tsx","../../../src/pages/Settings/Configurations/index.tsx","../../../src/api/api-keys/delete.ts","../../../src/api/api-keys/get.ts","../../../src/api/integrations/delete.ts","../../../src/api/integrations/execute.ts","../../../src/assets/images/Integrations/Types/PartnerApiKey.svg","../../../src/common/components/Integrations/CreateIntegrationCard.tsx","../../../src/common/components/Integrations/CreatePartnerApiCard.tsx","../../../src/common/components/Integrations/IntegrationCard.tsx","../../../src/api/api-keys/create.ts","../../../src/assets/images/Integrations/FormStages/ApiKey.svg","../../../src/assets/images/Integrations/FormStages/Key.svg","../../../src/common/components/Inputs/MultiTextField/index.tsx","../../../src/common/components/Integrations/PartnerApiModal.tsx","../../../src/pages/Settings/Integrations/index.tsx","../../../src/pages/Settings/Plugins/gmailText.tsx","../../../src/pages/Settings/Plugins/outlookText.tsx","../../../src/api/settings/get-settings.ts","../../../src/api/settings/update-settings.ts","../../../src/pages/Settings/Plugins/Plugins.tsx","../../../src/pages/Settings/AllowlistingTab/Domains.tsx","../../../src/assets/images/SettingsPage/onboarding-guide-book-image.png","../../../src/pages/Settings/AllowlistingTab/index.tsx","../../../src/pages/Settings/Settings.tsx","../../../src/pages/SimulationBuilder/index.tsx","../../../src/pages/TrainingCampaignDashboard/CompletionRate.tsx","../../../src/assets/images/box.svg","../../../src/pages/TrainingCampaignDashboard/EventsBarChart.tsx","../../../src/pages/TrainingCampaignDashboard/TableRowScore.tsx","../../../src/pages/TrainingCampaignDashboard/TrainingCampaignUsersTable.tsx","../../../src/pages/TrainingCampaignDashboard/index.tsx","../../../src/pages/TrainingCampaignView/TrainingCampaignTour.tsx","../../../src/pages/TrainingCampaignView/TrainingCampaignViewHeader.tsx","../../../src/pages/TrainingCampaignView/TrainingCampaignView.tsx","../../../src/assets/images/logo-stay-safe.svg","../../../src/pages/TrainingComplete/TrainingComplete.tsx","../../../src/api/member/get-stats.ts","../../../src/pages/UserProfile/EngagementChart.tsx","../../../src/pages/UserProfile/ExposureChart.tsx","../../../src/common/components/Tables/DateFilterV2.tsx","../../../src/api/member/get-campaigns.ts","../../../src/pages/UserProfile/UserCampaignsTable.tsx","../../../src/api/member/get.ts","../../../src/common/components/EditUserModal/EditUserModal.tsx","../../../src/pages/UserProfile/UserProfile.tsx","../../../src/api/analytics/export-scores.ts","../../../src/common/components/TimezoneFilter/TimezoneFilter.tsx","../../../src/common/components/UserTagsFilter/UserTagsFilter.tsx","../../../src/common/utils/download-url.ts","../../../src/pages/Users/DynamicGroupsTab/index.tsx","../../../src/assets/images/Integrations/Modal/DeleteIcon.png","../../../src/pages/Users/DeletionModal.tsx","../../../src/pages/Users/GroupsTab/GroupsTable.tsx","../../../src/pages/Users/GroupsTab/GroupsTab.tsx","../../../src/api/members/createMembersOffices.ts","../../../src/api/office/delete.ts","../../../src/pages/Users/OfficesTab/OfficesTable.tsx","../../../src/pages/Users/OfficesTab/OfficesTab.tsx","../../../src/api/members/createMembersGroups.ts","../../../src/api/member/delete.ts","../../../src/api/members/disable.ts","../../../src/api/members/enable.ts","../../../src/common/components/AddUserGroupsModal/AddUserGroupsModal.tsx","../../../src/common/components/AddUserOfficeModal/AddUserOfficeModal.tsx","../../../src/assets/images/Integrations/Modal/ConfirmationModal.png","../../../src/pages/Users/UsersTab/InactiveMembersModal.tsx","../../../src/pages/Users/UsersTab/UsersTable.tsx","../../../src/pages/Users/UsersTab/UsersTab.tsx","../../../src/common/components/MenuButton/index.tsx","../../../src/pages/Users/Users.tsx","../../../src/Routes/Routes.tsx","../../../src/common/components/ErrorBoundary/ErrorBoundary.tsx","../../../src/pages/LoadingScreen/LoadingScreen.tsx","../../../src/App.tsx","../../../src/index.tsx"],"sourcesContent":["import i18n from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\nimport englishTranslations from \"./assets/locales/en/translation\";\nimport hebrewTranslations from \"./assets/locales/he/translation\";\n\nconst resources = {\n en: { translation: englishTranslations },\n he: { translation: hebrewTranslations },\n};\n\ni18n\n .use(initReactI18next) // passes i18n down to react-i18next\n .init({\n resources,\n lng: \"en\",\n fallbackLng: \"en\",\n interpolation: {\n escapeValue: false, // react already safes from xss\n },\n react: {\n wait: true,\n },\n });\n\nexport default i18n;\n","export const ENV = import.meta.env.VITE_ENV\nexport const API_URL = import.meta.env.VITE_API_URL\nexport const EVENTS_API_URL = import.meta.env.VITE_EVENTS_API_URL\nexport const DASHBOARD_URL = import.meta.env.VITE_DASHBOARD_URL\nexport const CLOUDINARY_API_KEY = import.meta.env.VITE_CLOUDINARY_API_KEY\n// export const OPENAI_API_KEY = import.meta.env.VITE_OPENAI_API_KEY\nexport const OPENAI_MODEL = import.meta.env.VITE_OPENAI_MODEL\nexport const SENTRY_DSN = import.meta.env.VITE_SENTRY_DSN\nexport const HOTJAR_SITE_ID = import.meta.env.VITE_HOTJAR_SITE_ID\nexport const HOTJAR_VERSION = import.meta.env.VITE_HOTJAR_VERSION\nexport const RECAPTCHA_KEY = import.meta.env.VITE_RECAPTCHA_V3_KEY\n\nexport const NEW_LAUNCH_ANIMATION_DELAY_TIME = 30000 // 30 secconds\nexport const NEW_SAVE_ANIMATION_DELAY_TIME = 15000 // 15 secconds\n\nexport const AFTER_AI_SIMULATION_SAVE_ANIMATION_DELAY_TIME = 2900 // 2.9 second\n\nexport const LOWERCASE_REGEX = /[a-z]/\nexport const UPPERCASE_REGEX = /[A-Z]/\nexport const DIGITS_REGEX = /\\d/\nexport const SPECIAL_CHARACTERS_REGEX = /[ `!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?~]/\nexport const HTML_CLEAN_REGEX = /<[^>]+>/\nexport const DOMAIN_IP_REGEX =\n /\\b((25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])\\b|(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}/\nexport const DOMAIN_REGEX =\n /((http?):\\/\\/)?(www.)?[a-z0-9]+(\\.[a-z]{2,}){1,3}(#?\\/?[a-zA-Z0-9#]+)*\\/?(\\?[a-zA-Z0-9-_]+=[a-zA-Z0-9-%]+&?)?$/\nexport const IP_REGEX = /^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)(\\.(?!$)|$)){4}$/\nexport const PHONE_NUMNER_REGEX = /^\\+\\d{7,17}$/\nexport const PHONE_NUMNER_E164_REGEX = /^\\+\\d{7,17}$/\nexport const VALID_CUSTOMIZE_MICRO_TRAINING_URL =\n /^(https?:\\/\\/)?([a-zA-Z0-9.-]+)(:[0-9]{1,5})?(\\/[^\\s]*)?(\\?[^\\s]*)?(#[^\\s]*)?$/\nexport const ISO_DATE_TIME = 'YYYY-MM-DDTHH:mm'\nexport const ISO_DATE = 'YYYY-MM-DD'\nexport const US_DATE = 'MM-DD-YYYY'\nexport const SHORT_EU_DATE = 'DD/MM/YY'\nexport const US_DATE_WITH_MONTH_NAME = 'MMM DD, YYYY'\nexport const US_DATE_TIME_WITH_MONTH_NAME = 'MMM DD YYYY, HH:mm'\nexport const EU_DATE_TIME_12HR = 'DD/MM/YYYY hh:mm a'\nexport const EU_DATE_TIME_24HR = 'DD/MM/YYYY hh:mm'\nexport const MONTH_DAY = 'MMM DD'\nexport const HOUR_MINUTE_TIME = 'HH:mm'\n\nexport const ALL_DATA_LIMIT = { limit: 3000000 }\n\nexport const DOMAIN_VERIFY_REFRESH_DEBOUNCE = 6000\n","import axios from 'axios'\nimport { API_URL } from '../constants'\nimport { useQuery } from 'react-query'\nimport { ServerError } from '../types'\nimport { OrganizationState } from '@/types/organizations'\nimport { Domain } from '@/types/domains'\n\n//TODO: This\nexport type ClientDetailsResult = {\n _id: string\n name: string\n admin: string\n type: string\n default_language: string\n default_timezone: string\n campaigns_quota: number\n users_quota: number\n countries: string[]\n market_sectors: string[]\n velocity: 'weekly' | 'monthly' | 'quarterly'\n brands: string[]\n awareness_last_30_days: number[]\n domains: Domain[]\n whitelist: boolean\n industry: string\n baseline: boolean\n baseline_execution: number\n onboarding: boolean\n simulator_enabled: boolean\n ad_enabled: boolean\n mfa_enabled: boolean\n allow_unverified_domains: boolean\n offices: {\n _id: string\n name: string\n geo_location: string\n time_zone: string\n working_hours: string\n language: string\n client_id: string\n }[]\n logo?: string\n origin_country: string\n members: { active: number; total: number }\n parent_name?: string\n state?: OrganizationState\n gws_enabled?: boolean\n}\n\nexport async function getClientDetails() {\n const url = `${API_URL}/organizations/details/`\n const { data } = await axios.get(url, { withCredentials: true })\n return data\n}\n\nexport function useClientDetails() {\n return useQuery('organizations', getClientDetails)\n}\n","import axios from 'axios'\nimport { useQuery } from 'react-query'\nimport { API_URL } from '../constants'\nimport { ServerError } from '../types'\n\nexport type CurrentUser = {\n id: string\n username: string\n full_name?: string\n mfa_enabled?: boolean | null\n current_client_id: string\n has_multiple_clients: boolean\n saved_assets?: string[]\n saved_asset_packages?: string[]\n role?: string\n accepted_latest_terms: boolean\n mfa?: boolean\n mfa_type?: 'email' | 'app'\n}\n\nexport const getCurrentUser = async () => {\n const url = `${API_URL}/profile/`\n const { data } = await axios.get(url, { withCredentials: true })\n return data\n}\n\n//TODO : change all the 'user' api's to use the tanstak-qury!\nexport const useCurrentUser = () => {\n return useQuery('user', getCurrentUser, {\n retry: false,\n notifyOnStatusChange: false,\n refetchOnWindowFocus: false,\n })\n}\n","import { createContext, ReactNode, useContext, useEffect, useState } from 'react'\n\nimport { useClientDetails } from '@/api/client/client'\nimport { CurrentUser, useCurrentUser } from '../api/profile/current-user'\n\ntype AuthContextValue = {\n user: CurrentUser | undefined\n isLoading: boolean\n isError: boolean\n organizationState: any\n}\nexport const AuthContext = createContext({\n user: undefined,\n isLoading: true,\n isError: false,\n organizationState: undefined,\n})\n\nexport default function AuthProvider({ children }: { children: ReactNode }) {\n const { data: currentUser, isLoading: CurrentUserLoading, isError, refetch } = useCurrentUser()\n const { data: organizationDetails, isLoading: organizatioDetailsLoading } = useClientDetails()\n const [isTabVisible, setIsTabVisible] = useState(true)\n\n // Refetch when back to Tab\n document.addEventListener('visibilitychange', () => {\n setIsTabVisible(document.visibilityState === 'visible')\n })\n useEffect(() => {\n isTabVisible && refetch()\n }, [isTabVisible])\n\n return (\n \n {children}\n \n )\n}\n\nexport const useAuth = () => {\n return useContext(AuthContext)\n}\n","import axios from \"axios\";\nimport { useQuery } from \"react-query\";\n\nimport { API_URL } from \"../constants\";\nimport { ServerError } from \"../types\";\nimport { useAuth } from \"../../context/Auth\";\n\nexport type App = {\n _id: string;\n title: string;\n description: string;\n url: string;\n enabled: boolean;\n external: boolean;\n onboarded: boolean;\n key: string;\n package?: string;\n};\n\nexport async function getApps() {\n const appsUrl = `${API_URL}/apps/all`;\n const {\n data: { data: allApps },\n } = await axios.get(appsUrl, { withCredentials: true });\n return allApps;\n}\n\nexport function useApps() {\n const { user } = useAuth();\n\n return useQuery(\"apps\", getApps, {\n refetchOnWindowFocus: false,\n enabled: !!user,\n });\n}\n","export default \"__VITE_ASSET__f02c4c31__\"","export default \"__VITE_ASSET__391d5d22__\"","export default \"__VITE_ASSET__ece426a7__\"","// from MUI colors\nconst white = '#ffffff'\nconst black = '#000000'\nconst grey = {\n 50: '#FAFAFA',\n 100: '#F5F5F5',\n 200: '#EEEEEE',\n 300: '#E0E0E0',\n 400: '#BDBDBD',\n 500: '#9E9E9E',\n 600: '#757575',\n 700: '#616161',\n 800: '#424242',\n 900: '#212121',\n}\n\nconst blue = {\n 50: '#E3F2FD',\n 100: '#BBDEFB',\n 200: '#90CAF9',\n 300: '#64B5F6',\n 400: '#42A5F5',\n 500: '#2196F3',\n 600: '#1E88E5',\n 700: '#1976D2',\n 800: '#1565C0',\n 900: '#0D47A1',\n}\n\nconst red = {\n 50: '#FFEBEE',\n 100: '#FFCDD2',\n 200: '#EF9A9A',\n 300: '#E57373',\n 400: '#EF5350',\n 500: '#F44336',\n 600: '#E53935',\n 700: '#D32F2F',\n 800: '#C62828',\n 900: '#B71C1C',\n}\n\nconst deepPurple = {\n 50: '#EDE7F6',\n 100: '#D1C4E9',\n 200: '#B39DDB',\n 300: '#9575CD',\n 400: '#7E57C2',\n 500: '#673AB7',\n 600: '#5E35B1',\n 700: '#512DA8',\n 800: '#4527A0',\n 900: '#311B92',\n}\n\nconst indigo = {\n 50: '#E8EAF6',\n 100: '#C5CAE9',\n 200: '#9FA8DA',\n 300: '#7986CB',\n 400: '#5C6BC0',\n 500: '#3F51B5',\n 600: '#3949AB',\n 700: '#303F9F',\n 800: '#283593',\n 900: '#1A237E',\n}\n\nconst purple = {\n 50: '#F3E5F5',\n 100: '#E1BEE7',\n 200: '#CE93D8',\n 300: '#BA68C8',\n 400: '#AB47BC',\n 500: '#9C27B0',\n 600: '#8E24AA',\n 700: '#7B1FA2',\n 800: '#6A1B9A',\n 900: '#4A148C',\n}\n\nconst pink = {\n 50: '#FCE4EC',\n 100: '#F8BBD0',\n 200: '#F48FB1',\n 300: '#F06292',\n 400: '#EC407A',\n 500: '#E91E63',\n 600: '#D81B60',\n 700: '#C2185B',\n 800: '#AD1457',\n 900: '#880E4F',\n}\n\nconst amber = {\n 50: '#FFF8E1',\n 100: '#FFECB3',\n 200: '#FFE082',\n 300: '#FFD54F',\n 400: '#FFCA28',\n 500: '#FFC107',\n 600: '#FFB300',\n 700: '#FFA000',\n 800: '#FF8F00',\n 900: '#FF6F00',\n}\n\nconst green = {\n 50: '#E8F5E9',\n 100: '#C8E6C9',\n 200: '#A5D6A7',\n 300: '#81C784',\n 400: '#66BB6A',\n 500: '#4CAF50',\n 600: '#43A047',\n 700: '#388E3C',\n 800: '#2E7D32',\n 900: '#1B5E20',\n}\n\nconst lime = {\n 50: '#F9FBE7',\n 100: '#F0F4C3',\n 200: '#E6EE9C',\n 300: '#DCE775',\n 400: '#D4E157',\n 500: '#CDDC39',\n 600: '#C0CA33',\n 700: '#AFB42B',\n 800: '#9E9D24',\n 900: '#827717',\n}\n\n// const brown = {\n// 50: '#EFEBE9',\n// 100: '#D7CCC8',\n// 200: '#BCAAA4',\n// 300: '#A1887F',\n// 400: '#8D6E63',\n// 500: '#795548',\n// 600: '#6D4C41',\n// 700: '#5D4037',\n// 800: '#4E342E',\n// 900: '#3E2723',\n// }\n\n// const deepOrange = {\n// 50: '#FBE9E7',\n// 100: '#FFCCBC',\n// 200: '#FFAB91',\n// 300: '#FF8A65',\n// 400: '#FF7043',\n// 500: '#FF5722',\n// 600: '#F4511E',\n// 700: '#E64A19',\n// 800: '#D84315',\n// 900: '#BF360C',\n// }\n\n// const yellow = {\n// 50: '#FFFDE7',\n// 100: '#FFF9C4',\n// 200: '#FFF59D',\n// 300: '#FFF176',\n// 400: '#FFEE58',\n// 500: '#FFEB3B',\n// 600: '#FDD835',\n// 700: '#FBC02D',\n// 800: '#F9A825',\n// 900: '#F57F17',\n// }\n\n// Custom and override colors:\nconst blueGray = {\n 50: '#E9EEF5',\n 100: '#CFDCE8',\n 200: '#A4BDD5',\n 300: '#739ABD',\n 400: '#517FA6',\n 500: '#3E658B',\n 600: '#335171',\n 700: '#2E465E',\n 800: '#2A3C50',\n 900: '#141C26',\n}\nconst cyan = {\n 50: '#E1FBFD',\n 100: '#B4F4FB',\n 200: '#82EDF9',\n 300: '#50E6F6',\n 400: '#2BE0F4',\n 500: '#05DBF2',\n 600: '#04D7F0',\n 700: '#04D2EE',\n 800: '#03CDEC',\n 900: '#01C4E8',\n}\nconst teal = {\n 50: '#E1FCFB',\n 100: '#B5F8F6',\n 200: '#83F3F0',\n 300: '#51EEE9',\n 400: '#2CEBE5',\n 500: '#07E7E0',\n 600: '#06E4DC',\n 700: '#05E0D8',\n 800: '#04DDD3',\n 900: '#02D7CB',\n}\n\nconst lightBlue = {\n 50: '#E1F5FE',\n 100: '#B3E5FC',\n 200: '#81D4FA',\n 300: '#4FC3F7',\n 400: '#29B6F6',\n 500: '#03A9F4',\n 600: '#039BE5',\n 700: '#0288D1',\n 800: '#0277BD',\n 900: '#01579B',\n}\nconst blueDianne = {\n 50: '#F0FBFB',\n 100: '#DAF3F3',\n 200: '#B9E7E8',\n 300: '#88D6D8',\n 400: '#50BBC0',\n 500: '#349FA6',\n 600: '#2E838C',\n 700: '#2B6A73',\n 800: '#2B585F',\n 900: '#294D55',\n}\nconst orange = {\n 50: '#FEF1E0',\n 100: '#FDDBB3',\n 200: '#FCC380',\n 300: '#FAAB4D',\n 400: '#F99926',\n 500: '#F88700',\n 600: '#F77F00',\n 700: '#F67400',\n 800: '#F56A00',\n 900: '#F35700',\n}\nconst lightGreen = {\n 50: '#F8FEF1',\n 100: '#EDFEDB',\n 200: '#E1FDC3',\n 300: '#D4FCAB',\n 400: '#CBFB99',\n 500: '#C2FA87',\n 600: '#BCF97F',\n 700: '#B4F974',\n 800: '#ACF86A',\n 900: '#9FF657',\n}\n\nconst blueEyes = {\n 50: '#9AA7AF',\n 100: '#8F9DA6',\n 200: '#83929C',\n 300: '#768691',\n 400: '#677985',\n 500: '#576A78',\n 600: '#4E606C',\n 700: '#465761',\n 800: '#3F4E57',\n 900: '#39464E',\n}\n\nexport type ColorIndex = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900\n\nexport const palette = {\n // colors\n lightGreen,\n orange,\n blueDianne,\n lightBlue,\n teal,\n cyan,\n blueGray,\n amber,\n pink,\n purple,\n indigo,\n deepPurple,\n red,\n blue,\n grey,\n lime,\n green,\n blueEyes,\n black,\n white,\n\n //link is free - not in use\n link: {\n main: blue[900],\n },\n common: { black: black, white: white, focusBackground: grey[400] }, // remove focusBackground: grey[400]\n background: {\n paper: white,\n default: white,\n dark: blueGray[900],\n logo: cyan[500],\n codeBlock: blueGray[50],\n secondaryGradient: 'linear-gradient(136.67deg, rgba(70, 78, 147, 0.8) 8.34%, rgba(42, 38, 137, 0.8) 95.26%)',\n successGradient: 'linear-gradient(246.26deg, #00b09b, #96c93d)',\n errorGradient: 'linear-gradient(246.26deg, #cb2d3e, #ef473a)',\n warningGradient: 'linear-gradient(246.26deg, #ffb75e, #ed8f03)',\n neutralGradient:\n 'linear-gradient(180deg, #464E93 0%, rgba(173, 89, 164, 0.441435) 99.99%, rgba(255, 98, 177, 0.0001) 100%)',\n },\n divider: 'rgba(0,0,0,0.1)',\n //primary is free - not in use\n primary: {\n light: grey[800],\n main: blueGray[900],\n dark: black,\n contrastText: cyan[500],\n },\n //secondary is free - not in use\n secondary: {\n light: cyan[300],\n main: cyan[500],\n dark: blueDianne[600],\n contrastText: black,\n },\n error: {\n light: purple[100],\n main: red[900],\n dark: pink[800],\n contrastText: white,\n },\n success: {\n light: '#2dce9f',\n main: '#2bb596',\n dark: '#008468',\n contrastText: black,\n },\n warning: {\n light: amber[300],\n main: orange[400],\n dark: amber[700],\n contrastText: black,\n },\n text: {\n primary: blueDianne[900],\n disabled: '#858f9f',\n code: '#ea205c',\n },\n}\n","import {\n faBadgeCheck,\n faExclamationCircle,\n faExclamationSquare,\n faExclamationTriangle,\n} from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { ReactNode } from 'react'\n\nimport { palette } from '../palette'\n\nconst iconMapping: Record<'success' | 'info' | 'warning' | 'error', ReactNode> = {\n success: ,\n info: ,\n warning: ,\n error: ,\n}\n\nexport const MuiAlertTitle = {\n styleOverrides: {\n root: {\n fontWeight: 'bold',\n },\n },\n}\nexport const MuiAlert = {\n defaultProps: {\n iconMapping,\n },\n styleOverrides: {\n root: {\n alignItems: 'flex-start',\n padding: '16px 16px 12px',\n },\n icon: {\n fontSize: '32px',\n },\n message: {\n fontSize: '14px',\n fontWeight: 500,\n lineHeight: '32px',\n },\n standard: {\n border: 'none',\n '& .MuiAlert-message': {\n color: palette.blueDianne[900],\n },\n },\n filled: {\n padding: '17px 16px 13px',\n border: 'none',\n color: palette.black,\n },\n outlined: {\n '& .MuiAlert-message': {\n color: palette.blueDianne[900],\n },\n },\n standardSuccess: {\n '& .MuiAlert-icon': {\n color: palette.green[500],\n },\n backgroundColor: palette.green[50],\n },\n standardInfo: {\n '& .MuiAlert-icon': {\n color: palette.blue[500],\n },\n backgroundColor: palette.blue[50],\n },\n standardWarning: {\n '& .MuiAlert-icon': {\n color: palette.orange[900],\n },\n backgroundColor: palette.orange[50],\n },\n standardError: {\n '& .MuiAlert-icon': {\n color: palette.red[900],\n },\n backgroundColor: palette.red[50],\n },\n\n filledSuccess: {\n backgroundColor: palette.green[500],\n },\n filledInfo: {\n backgroundColor: palette.blue[500],\n },\n filledWarning: {\n backgroundColor: palette.orange[400],\n },\n filledError: {\n color: palette.white,\n\n backgroundColor: palette.red[900],\n },\n\n outlinedSuccess: {\n '& .MuiAlert-icon': {\n color: palette.green[500],\n },\n borderColor: palette.green[500],\n },\n outlinedInfo: {\n '& .MuiAlert-icon': {\n color: palette.blue[500],\n },\n borderColor: palette.blue[500],\n },\n outlinedWarning: {\n '& .MuiAlert-icon': {\n color: palette.orange[900],\n },\n borderColor: palette.orange[400],\n },\n outlinedError: {\n '& .MuiAlert-icon': {\n color: palette.red[900],\n },\n borderColor: palette.red[900],\n },\n action: {\n button: {\n color: palette.black,\n },\n height: '100%',\n alignItems: 'center',\n padding: '16px',\n },\n },\n}\n","export const typography: {\n fontFamily: string\n fontWeightExtraBold: number\n fontWeightBold: number\n fontWeightSemiBold: number\n fontWeightMedium: number\n fontWeightRegular: number\n fontWeightLight: number\n} = {\n fontFamily: ['Montserrat', 'Nunito', 'Roboto', 'sans-serif'].join(','),\n // usuing the default MUI weights\n fontWeightExtraBold: 900,\n fontWeightBold: 700,\n fontWeightSemiBold: 600,\n fontWeightMedium: 500,\n fontWeightRegular: 400,\n fontWeightLight: 300,\n}\n","import { palette } from '../palette'\nimport { typography } from '../typography'\n\nexport const MuiButton = {\n defaultProps: {\n disableRipple: true,\n },\n styleOverrides: {\n root: {\n whiteSpace: 'nowrap',\n letterSpacing: '0.02857em',\n textTransform: 'capitalize',\n minWidth: 'fit-content',\n fontWeight: typography.fontWeightMedium,\n fontSize: '16px',\n padding: '6px 16px',\n // margin: '4px', // Removed to work GroupButtons... button shuold no have margin\n height: '32px',\n boxShadow: 'none',\n borderRadius: 100,\n '&:hover , &:active': { boxShadow: 'none' },\n '& .MuiButton-startIcon, & .MuiButton-endIcon': {\n '& svg': {\n fontSize: '18px',\n },\n },\n },\n sizeLarge: {\n fontSize: '18px',\n height: '40px',\n padding: '1px 16px 0px',\n '& .MuiButton-startIcon, & .MuiButton-endIcon': {\n '& svg': {\n fontSize: '20px',\n },\n },\n },\n sizeSmall: {\n fontSize: '12px',\n height: '24px',\n padding: '6px 8px',\n '& .MuiButton-startIcon, & .MuiButton-endIcon': {\n '& svg': {\n fontSize: '14px',\n },\n },\n },\n text: {\n color: palette.blueDianne[900],\n fontWeight: typography.fontWeightBold,\n background: 'none',\n '&:hover': {\n background: palette.blueDianne[50],\n },\n '&:active': {\n background: palette.blueDianne[100],\n },\n '&:disabled': {\n color: palette.grey[600],\n },\n },\n textSecondary: {\n color: palette.white,\n fontWeight: typography.fontWeightBold,\n background: 'none',\n '&:hover': {\n background: palette.blueDianne[600],\n },\n '&:active': {\n background: palette.blueDianne[800],\n },\n '&:disabled': {\n color: palette.grey[600],\n },\n },\n outlined: {\n color: palette.black,\n background: palette.white,\n borderColor: palette.cyan[500],\n '&:hover': {\n background: palette.blueDianne[50],\n borderColor: palette.cyan[500],\n '&:active': {\n background: palette.blueDianne[100],\n },\n },\n\n '&:disabled': {\n color: palette.grey[600],\n background: 'none',\n borderColor: palette.grey[400],\n },\n },\n contained: {\n color: palette.black,\n background: palette.cyan[500],\n '&:hover': {\n background: palette.blueDianne[600],\n },\n '&:active': {\n background: palette.blueDianne[800],\n },\n '&:disabled': {\n color: palette.grey[600],\n background: palette.grey[300],\n border: '1px solid',\n borderColor: palette.grey[400],\n },\n },\n\n containedSecondary: {\n color: palette.cyan[500],\n background: palette.blueGray[900],\n border: '1px solid',\n borderColor: palette.cyan[500],\n '&:hover': {\n background: palette.blueGray[700],\n },\n '&:active': {\n background: palette.blueGray[800],\n },\n '&:disabled': {\n color: palette.grey[600],\n background: palette.grey[300],\n border: '1px solid',\n borderColor: palette.grey[400],\n },\n },\n },\n}\n","import { palette } from '../palette'\n\nexport const MuiCheckbox = {\n styleOverrides: {\n root: {\n width: '19px',\n height: '19px',\n padding: '9px',\n overflow: 'hidden',\n margin: '11px',\n // *** Unchecked - Unactive *** :\n color: 'transparent',\n background: palette.white,\n border: '1px solid',\n borderColor: palette.blueGray[900],\n borderRadius: '4px',\n\n // Unchecked - Unactive - Hover:\n '&:hover': {\n background: palette.white,\n boxShadow: `0 0 0 10px ${palette.grey[300]}`,\n },\n '&:active': {\n boxShadow: `0 0 0 10px ${palette.grey[400]}`,\n },\n // Unchecked - Unactive - Disabled:\n '&.Mui-disabled': {\n borderColor: palette.grey[400],\n color: 'transparent',\n background: palette.grey[50],\n },\n\n //for SCD issue\n '& input': {\n position: 'absolute !important',\n width: '100% !important',\n },\n\n // *** Checked - Active *** :\n '&.Mui-checked': {\n background: palette.blueGray[900],\n borderColor: palette.blueGray[900],\n color: palette.cyan[500],\n // Checked - Active - Hover:\n '&:hover': {\n boxShadow: `0 0 0 10px ${palette.cyan[50]}`,\n },\n '&:active': {\n boxShadow: `0 0 0 10px ${palette.cyan[200]}`,\n },\n // Checked - Active - Disabled:\n '&.Mui-disabled': {\n color: palette.grey[400],\n borderColor: palette.grey[400],\n background: palette.grey[600],\n },\n },\n },\n sizeSmall: {\n width: '15px',\n height: '15px',\n padding: '7px',\n },\n },\n}\n","import { palette } from '../palette'\nimport { typography } from '../typography'\n\ndeclare module '@mui/material/Chip' {\n interface ChipPropsVariantOverrides {\n tag: true\n filter: true\n }\n}\n\nexport const MuiChip = {\n defaultProps: {\n variant: 'filled',\n color: 'primary',\n size: 'medium',\n },\n styleOverrides: {\n root: {\n minWidth: 'fit-content',\n fontWeight: typography.fontWeightMedium,\n fontSize: '14px',\n padding: '1px',\n margin: '4px',\n height: '32px',\n borderRadius: 100,\n background: palette.blue[100],\n color: palette.black,\n '& .MuiChip-icon': {\n width: '12px',\n height: '12px',\n },\n '&:hover': {\n background: palette.blue[300],\n },\n '&:active': {\n background: palette.blue[500],\n },\n '&.Mui-disabled': {\n color: palette.grey[600],\n background: palette.grey[300],\n border: '1px solid',\n borderColor: palette.grey[400],\n opacity: 1,\n '.MuiChip-deleteIcon': {\n color: palette.grey[500],\n },\n '.MuiChip-avatar': {\n color: palette.grey[600],\n background: palette.grey[500],\n },\n },\n },\n sizeSmall: {\n fontSize: '12px',\n height: '24px',\n },\n\n outlined: {\n background: palette.white,\n borderColor: palette.blue[100],\n '&:hover': {\n background: palette.lightBlue[50],\n },\n '&:active': {\n background: palette.lightBlue[100],\n },\n },\n\n deleteIcon: {\n color: palette.blue[600],\n '&:hover': {\n color: palette.blue[600],\n },\n },\n deleteIconColorSecondary: {\n color: palette.blueDianne[600],\n '&:hover': {\n color: palette.blueDianne[600],\n },\n },\n\n avatar: {\n color: palette.black,\n background: palette.grey[400],\n },\n colorSecondary: {\n background: palette.blueDianne[200],\n color: palette.black,\n '&:hover': {\n background: palette.blueDianne[300],\n },\n '&:active': {\n background: palette.blueDianne[400],\n },\n '&.Mui-disabled': {\n color: palette.grey[600],\n background: palette.grey[300],\n border: '1px solid',\n borderColor: palette.grey[400],\n },\n },\n },\n variants: [\n {\n props: { variant: 'tag' },\n style: {\n backgroundColor: palette.cyan[100],\n color: palette.blueDianne[900],\n borderRadius: '5px',\n '&:hover': {\n background: palette.cyan[100],\n },\n '&:active': {\n background: palette.cyan[100],\n },\n '&.MuiChip-colorSecondary': {\n backgroundColor: palette.pink[600],\n color: palette.white,\n fontWeight: 'bold',\n '&.Mui-disabled': {\n color: palette.grey[600],\n background: palette.grey[300],\n border: '1px solid',\n borderColor: palette.grey[400],\n },\n },\n },\n },\n {\n props: { variant: 'filter' },\n style: {\n backgroundColor: palette.grey[400],\n color: palette.blueDianne[900],\n borderRadius: '5px',\n cursor: 'pointer',\n '&:hover': {\n background: palette.grey[300],\n },\n '&:active': {\n background: palette.grey[500],\n },\n '&.MuiChip-colorSecondary': {\n backgroundColor: palette.cyan[500],\n '&:hover': {\n background: palette.blueDianne[600],\n },\n '&:active': {\n background: palette.blueDianne[700],\n },\n },\n },\n },\n ],\n}\n","import { palette } from '../palette'\n\nexport const MuiIconButton = {\n defaultProps: {\n disableRipple: true,\n },\n styleOverrides: {\n root: {\n '&:hover': {\n background: palette.cyan[900] + 20,\n },\n '&:active': {\n background: palette.cyan[900] + 40,\n },\n },\n },\n}\n","import { palette } from '../palette'\n\nexport const MuiMenuItem = {\n defaultProps: {\n disableRipple: true,\n },\n styleOverrides: {\n root: {\n '&:hover': {\n background: palette.blueDianne[50],\n },\n '&:active': {\n background: palette.blueDianne[100],\n },\n },\n },\n}\n","export const MuiPaper = {\n defaultProps: {\n elevation: 0,\n },\n styleOverrides: {\n root: {\n boxShadow: 'none',\n border: '1.5px solid rgba(0,0,0,0.1)',\n },\n },\n}\n","import { palette } from '../palette'\n\nexport const MuiRadio = {\n defaultProps: {\n disableRipple: true,\n },\n styleOverrides: {\n root: {\n width: '38px',\n height: '38px',\n '&.Mui-checked': {\n '& .MuiSvgIcon-root': {\n background: palette.blueDianne[900],\n border: `2.5px solid ${palette.cyan[500]}`,\n width: '14px',\n height: '14px',\n overFlow: 'hidden',\n },\n '&:hover': {\n background: palette.cyan[50],\n },\n '&:active': {\n background: palette.cyan[200],\n },\n },\n '& .MuiSvgIcon-root': {\n borderRadius: 100,\n background: palette.white,\n boxSizing: 'border-box',\n boxShadow: `0 0 0 2px ${palette.blueDianne[900]}`,\n fill: 'transparent',\n width: '14px',\n height: '14px',\n overFlow: 'hidden',\n },\n '&:hover': {\n background: palette.grey[300],\n },\n '&:active': {\n background: palette.grey[400],\n },\n '&.Mui-disabled': {\n '&.Mui-checked .MuiSvgIcon-root': {\n background: palette.grey[500],\n borderColor: palette.grey[50],\n },\n '& .MuiSvgIcon-root': {\n boxShadow: `0 0 0 2px ${palette.grey[500]}`,\n background: palette.grey[50],\n },\n '&:hover': {\n background: 'none',\n },\n },\n },\n },\n}\n","export const MuiTab = {\n defaultProps: {\n disableRipple: true,\n },\n styleOverrides: {\n root: {\n minHeight: 36.5,\n minWidth: 80,\n padding: '2px 12px 0px',\n '@media(min-width: 600px)': {\n minWidth: 80,\n },\n },\n textColorPrimary: {\n '& .Mui-selected': {\n color: '#181F2A',\n transition: 'color .5s',\n },\n },\n },\n}\n\nexport const MuiTabs = {\n styleOverrides: {\n root: {\n backgroundColor: '#fff',\n borderRadius: 10,\n minHeight: 36.5,\n color: '#181F2A',\n '& .Mui-selected': {\n color: '#181F2A',\n transition: 'color .5s',\n },\n },\n flexContainer: {\n display: 'inline-flex',\n position: 'relative',\n zIndex: 1,\n },\n scroller: {\n padding: '0 8px',\n },\n indicator: {\n bottom: 0,\n right: 3,\n left: 3,\n\n height: '100%',\n background: 'none',\n minWidth: 80,\n position: 'absolute',\n '&:after': {\n content: '\"\"',\n display: 'block',\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n height: 3,\n borderRadius: 50,\n backgroundColor: '#000',\n },\n },\n },\n}\n","export const MuiTable = {\n defaultProps: {\n size: 'small',\n },\n styleOverrides: {\n root: {\n boxShadow: 'none',\n },\n },\n}\n\nexport const MuiTableRow = {\n styleOverrides: {\n root: { height: 61 },\n },\n}\n\nexport const MuiTableCell = {\n styleOverrides: {\n body: {\n color: '#294D55',\n },\n footer: {\n border: 'none',\n borderTop: '1.5px solid rgba(0,0,0,0.1)',\n },\n },\n}\n","export default \"__VITE_ASSET__a32e2e7e__\"","import { palette } from '../palette'\nimport LockDark from '@/assets/images/switch/locked-light.svg'\n\nexport const MuiSwitch = {\n defaultProps: {\n disableRipple: true,\n },\n styleOverrides: {\n root: {\n marginTop: '-2px',\n '&.locked': {\n '& .MuiSwitch-thumb': {\n backgroundImage: `url(${LockDark})`,\n color: palette.blueDianne[900],\n backgroundRepeat: 'no-repeat',\n backgroundPosition: 'center',\n },\n '& .MuiSwitch-track': {\n backgroundColor: `${palette.cyan[500]} !important`,\n outline: `1px solid ${palette.blueDianne[900]} !important`,\n opacity: 1,\n },\n },\n },\n switchBase: {\n padding: 8,\n color: palette.white,\n '&.Mui-checked': {\n color: palette.blueDianne[900],\n transform: 'translateX(16px)',\n '& + .MuiSwitch-track': {\n backgroundColor: `${palette.cyan[500]} `,\n outline: `1px solid ${palette.blueDianne[900]}`,\n opacity: 1,\n },\n '&:hover': {\n background: `${palette.cyan[200]}50`,\n '&:active': {\n background: `${palette.cyan[700]}50`,\n },\n },\n },\n '&.Mui-disabled': {\n color: palette.grey[600],\n '& + .MuiSwitch-track': {\n backgroundColor: `${palette.grey[400]} `,\n outline: `1px solid ${palette.grey[600]}`,\n opacity: 1,\n },\n },\n '&.Mui-disabled.Mui-checked': {\n color: palette.grey[600],\n '& + .MuiSwitch-track': {\n backgroundColor: `${palette.grey[400]}`,\n outline: `1px solid ${palette.grey[600]}`,\n opacity: 1,\n },\n },\n },\n track: {\n borderRadius: 15,\n backgroundColor: palette.grey[400],\n outline: `1px solid ${palette.grey[600]}`,\n height: 16,\n width: 32,\n position: 'relative',\n opacity: 1,\n },\n thumb: {\n boxShadow: 'none',\n width: 14,\n height: 14,\n margin: 5,\n },\n colorSecondary: {\n color: palette.cyan[500],\n '&:hover': {\n background: `${palette.cyan[200]}50`,\n },\n '& + .MuiSwitch-track': {\n backgroundColor: `${palette.blueDianne[900]} !important`,\n outline: `1px solid ${palette.cyan[500]}`,\n opacity: 1,\n },\n '&.Mui-checked': {\n color: palette.cyan[500],\n transform: 'translateX(16px)',\n '& + .MuiSwitch-track': {\n backgroundColor: `${palette.blueDianne[900]} !important`,\n outline: `1px solid ${palette.cyan[500]}`,\n opacity: 1,\n },\n '&:hover': {\n background: `${palette.cyan[200]}50`,\n },\n '&:active': {\n background: `${palette.cyan[700]}50`,\n },\n },\n '&:active': {\n background: `${palette.cyan[700]}50`,\n },\n },\n },\n}\n","export const MuiCard = {\n styleOverrides: {\n root: {\n border: 'none',\n padding: '32px',\n borderRadius: '10px',\n height: '100%',\n },\n },\n}\n","import { palette } from '../palette'\n\nexport const MuiMenu = {\n styleOverrides: {\n root: {\n marginTop: '10px',\n boxShadow: 'none',\n '.MuiPaper-root': {\n minWidth: '240px',\n border: `1px solid ${palette.cyan[500]}`,\n borderRadius: '10px',\n '.MuiMenu-list': {\n padding: 0,\n '.MuiMenuItem-root:first-of-type': {\n paddingTop: '16px',\n },\n '.MuiMenuItem-root:last-of-type': {\n paddingBottom: '16px',\n },\n },\n },\n },\n },\n}\n","export const MuiButtonGroup = {\n defaultProps: {\n disableRipple: true,\n },\n styleOverrides: {\n root: {\n boxShadow: 'none',\n },\n grouped: {\n border: 'none !important',\n },\n },\n}\n","import { MuiAlert, MuiAlertTitle } from './MuiAlert'\nimport { MuiButton } from './MuiButton'\nimport { MuiCheckbox } from './MuiCheckbox'\nimport { MuiChip } from './MuiChip'\nimport { MuiIconButton } from './MuiIconButton'\nimport { MuiMenuItem } from './MuiMenuItem'\nimport { MuiPaper } from './MuiPaper'\nimport { MuiRadio } from './MuiRadio'\nimport { MuiTab, MuiTabs } from './MuiTab'\nimport { MuiTable, MuiTableCell, MuiTableRow } from './MuiTable'\nimport { MuiSwitch } from './MuiSwitch'\nimport { MuiCard } from './MuiCard'\nimport { MuiMenu } from './MuiMenu'\nimport { MuiButtonGroup } from './MuiButtonGroup'\n// import { MuiTextField } from './MuiTextField'\n\nexport const components = {\n MuiPaper,\n MuiTable,\n MuiTableRow,\n MuiTableCell,\n MuiChip,\n MuiButton,\n MuiCheckbox,\n MuiTabs,\n MuiTab,\n MuiAlert,\n MuiAlertTitle,\n MuiRadio,\n MuiIconButton,\n MuiMenuItem,\n MuiSwitch,\n MuiCard,\n MuiMenu,\n MuiButtonGroup,\n // MuiTextField, Dont import this coomponent befor migrating all the textfields to use custom TextField TextFieldV2\n}\n","import { CSSProperties } from 'react'\nimport { createTheme } from '@mui/material/styles'\nimport { palette } from './palette'\nimport { components } from './components'\nimport { Color } from '@mui/material'\nimport { typography } from './typography'\n\ndeclare module '@mui/material/styles/' {\n interface TypographyVariants {\n fontWeightSemiBold: React.CSSProperties['fontWeight']\n fontWeightExtraBold: React.CSSProperties['fontWeight']\n }\n interface TypographyVariantsOptions {\n fontWeightSemiBold?: React.CSSProperties['fontWeight']\n fontWeightExtraBold?: React.CSSProperties['fontWeight']\n }\n interface TypeBackground {\n dark?: CSSProperties['color']\n logo?: CSSProperties['color']\n codeBlock?: CSSProperties['color']\n secondaryGradient?: CSSProperties['color']\n successGradient?: CSSProperties['color']\n warningGradient?: CSSProperties['color']\n errorGradient?: CSSProperties['color']\n neutralGradient?: CSSProperties['color']\n }\n interface Palette {\n link: {\n main: string\n }\n lightGreen: Color\n orange: Color\n blueDianne: Color\n lightBlue: Color\n teal: Color\n cyan: Color\n blueGray: Color\n amber: Color\n pink: Color\n purple: Color\n indigo: Color\n deepPurple: Color\n red: Color\n blue: Color\n lime: Color\n grey: Color\n green: Color\n blueEyes: Color\n black: string\n white: string\n }\n interface TypeText {\n code?: CSSProperties['color']\n }\n interface CommonColors {\n focusBackground: string\n }\n}\nexport const theme = createTheme({\n palette,\n typography,\n shadows: [\n 'none',\n '0px 2px 5px -1px rgba(0,0,0,0.16),0px 1px 10px 0px rgba(0,0,0,0.12),0px 1px 15px 0px rgba(0,0,0,0.08)',\n '0px 3px 5px -2px rgba(0,0,0,0.16),0px 2px 10px 0px rgba(0,0,0,0.12),0px 1px 20px 0px rgba(0,0,0,0.08)',\n '0px 3px 5px -2px rgba(0,0,0,0.16),0px 3px 10px 0px rgba(0,0,0,0.12),0px 1px 20px 0px rgba(0,0,0,0.08)',\n '0px 2px 4px -1px rgba(0,0,0,0.16),0px 4px 5px 0px rgba(0,0,0,0.12),0px 1px 10px 0px rgba(0,0,0,0.08)',\n '0px 3px 5px -1px rgba(0,0,0,0.16),0px 5px 8px 0px rgba(0,0,0,0.12),0px 1px 14px 0px rgba(0,0,0,0.08)',\n '0px 3px 5px -1px rgba(0,0,0,0.16),0px 6px 10px 0px rgba(0,0,0,0.12),0px 1px 18px 0px rgba(0,0,0,0.08)',\n '0px 4px 5px -2px rgba(0,0,0,0.16),0px 7px 10px 1px rgba(0,0,0,0.12),0px 2px 16px 1px rgba(0,0,0,0.08)',\n '0px 5px 5px -3px rgba(0,0,0,0.16),0px 8px 10px 1px rgba(0,0,0,0.12),0px 3px 14px 2px rgba(0,0,0,0.08)',\n '0px 5px 6px -3px rgba(0,0,0,0.16),0px 9px 12px 1px rgba(0,0,0,0.12),0px 3px 16px 2px rgba(0,0,0,0.08)',\n '0px 6px 6px -3px rgba(0,0,0,0.16),0px 10px 14px 1px rgba(0,0,0,0.12),0px 4px 18px 3px rgba(0,0,0,0.08)',\n '0px 6px 7px -4px rgba(0,0,0,0.16),0px 11px 15px 1px rgba(0,0,0,0.12),0px 4px 20px 3px rgba(0,0,0,0.08)',\n '0px 7px 8px -4px rgba(0,0,0,0.16),0px 12px 17px 2px rgba(0,0,0,0.12),0px 5px 22px 4px rgba(0,0,0,0.08)',\n '0px 7px 8px -4px rgba(0,0,0,0.16),0px 13px 19px 2px rgba(0,0,0,0.12),0px 5px 24px 4px rgba(0,0,0,0.08)',\n '0px 7px 9px -4px rgba(0,0,0,0.16),0px 14px 21px 2px rgba(0,0,0,0.12),0px 5px 26px 4px rgba(0,0,0,0.08)',\n '0px 8px 9px -5px rgba(0,0,0,0.16),0px 15px 22px 2px rgba(0,0,0,0.12),0px 6px 28px 5px rgba(0,0,0,0.08)',\n '0px 8px 10px -5px rgba(0,0,0,0.16),0px 16px 24px 2px rgba(0,0,0,0.12),0px 6px 30px 5px rgba(0,0,0,0.08)',\n '0px 8px 11px -5px rgba(0,0,0,0.16),0px 17px 26px 2px rgba(0,0,0,0.12),0px 6px 32px 5px rgba(0,0,0,0.08)',\n '0px 9px 11px -5px rgba(0,0,0,0.16),0px 18px 28px 2px rgba(0,0,0,0.12),0px 7px 34px 6px rgba(0,0,0,0.08)',\n '0px 9px 12px -6px rgba(0,0,0,0.16),0px 19px 29px 2px rgba(0,0,0,0.12),0px 7px 36px 6px rgba(0,0,0,0.08)',\n '0px 10px 13px -6px rgba(0,0,0,0.16),0px 20px 31px 3px rgba(0,0,0,0.12),0px 8px 38px 7px rgba(0,0,0,0.08)',\n '0px 10px 13px -6px rgba(0,0,0,0.16),0px 21px 33px 3px rgba(0,0,0,0.12),0px 8px 40px 7px rgba(0,0,0,0.08)',\n '0px 10px 14px -6px rgba(0,0,0,0.16),0px 22px 35px 3px rgba(0,0,0,0.12),0px 8px 42px 7px rgba(0,0,0,0.08)',\n '0px 11px 14px -7px rgba(0,0,0,0.16),0px 23px 36px 3px rgba(0,0,0,0.12),0px 9px 44px 8px rgba(0,0,0,0.08)',\n '0px 11px 15px -7px rgba(0,0,0,0.16),0px 24px 38px 3px rgba(0,0,0,0.12),0px 9px 46px 8px rgba(0,0,0,0.08)',\n ],\n shape: {\n borderRadius: 15,\n },\n components,\n})\n","import { Box, Step, StepConnector, StepContent, StepLabel, Stepper, Typography } from '@mui/material'\nimport { stepConnectorClasses } from '@mui/material/StepConnector'\nimport { styled } from '@mui/system'\nimport { NavLink } from 'react-router-dom'\n\nimport logo from '@/assets/images/logo-be-awere-stay-safe.svg'\nimport fingerPrint from '@/assets/images/logo-light-blue.svg'\nimport rocket from '@/assets/images/rocket-with-line.png'\nimport { theme } from '@/theme/theme'\n\nconst CustomStepConnector = styled(StepConnector)(() => ({\n [`&.${stepConnectorClasses.root}`]: {\n [`& .${stepConnectorClasses.line}`]: {\n borderColor: theme.palette.blueGray[900],\n borderWidth: '0.5px',\n padding: 0,\n },\n },\n}))\n\nconst BlueDotIcon = styled('div')(() => ({\n width: '25px',\n height: '25px',\n padding: '0',\n margin: '-12px 0px',\n boxShadow: `0 0 0 1px ${theme.palette.black}`,\n backgroundColor: theme.palette.cyan[500],\n borderRadius: '50%',\n border: `4px solid ${theme.palette.common.white}`,\n position: 'relative',\n zIndex: 1,\n}))\n\nconst MicrosoftEntraIdInstructions = () => {\n return (\n \n \n {' '}\n How To Authenticate Microsoft Entra ID\n \n \n }>\n \n }>{'Tenant ID'}\n \n \n • Sign into the Azure portal and navigate to the{' '}\n \n Microsoft Entra ID\n {' '}\n section\n \n \n • Find your tenant ID and copy paste it in the Cywareness platform{' '}\n \n \n \n \n }>{'Application ID'}\n \n \n • Click on “App registrations” on your left panel and then “New registration”{' '}\n \n \n Step 1: Enter name for application (E.g. “Cywareness AD Integration”)\n \n \n Step 2: In supported account types choose: “Accounts in any organizational directory”\n \n\n \n Step 3: Redirect URI can be left empty\n \n\n \n Step 4: In the “Essentials” section find Application ID. Copy and paste it into Cywareness\n platform\n \n \n \n \n }>{'Client Secret'}\n \n \n • After registering, navigate to the “API permissions” section on your left panel of the newly\n registered application\n \n \n Step 1: Click “Add a permission” and on the “Microsoft Graph” panel click “Application\n permission” and add a) Group.Read.All, b) User.Read.All\n \n \n Step 2: Click “Grant admin consent”\n \n \n • Once permissions are granted navigate to the “Certificates & Secrets” > “Client Secrets” section on\n your left panel and click “New Client Secret”\n \n \n Step 1: Provide description (E.g. “Cywareness Client Secret”)\n \n \n Step 2: Set to Expire in (E.g. “365 days, 12 months”)\n \n \n Step 3: Click “Add”\n \n \n • Once added, copy the “Value” of the secret and paste it into the “Client Secret” field in the\n Cywareness platform\n \n \n \n \n \n \n \n \n \n \n \n )\n}\n\nexport default MicrosoftEntraIdInstructions\n","export default \"__VITE_ASSET__bd9117b9__\"","import { LayoutContext } from '@/common/components/Layout/Layout'\nimport { useContext } from 'react'\nimport { useNavigate as useReactRouterNavigate } from 'react-router-dom'\n\n//WithBlocker\nconst useNavigateWithLayoutBlocker: () => any = () => {\n const { navigationBlock, setBlockedNavigationRequest } = useContext(LayoutContext)\n const navigation = useReactRouterNavigate()\n if (navigationBlock) {\n return (destination: string) => {\n setBlockedNavigationRequest(destination)\n }\n }\n return navigation\n}\n\nexport default useNavigateWithLayoutBlocker\n","import { ReactElement } from 'react'\nimport { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material/'\nimport { useTranslation } from 'react-i18next'\n\nimport makeStyles from '@mui/styles/makeStyles'\nimport createStyles from '@mui/styles/createStyles'\n\ntype AlertProps = {\n buttonLabel?: string\n dialogTitle?: string\n dialogText?: string | string[]\n dialogContent?: string | ReactElement\n onConfirm?: () => void\n handleClose: () => void\n open: boolean\n cancelButton?: boolean\n confirmButton?: boolean\n closeOnClick?: boolean\n}\n\nconst Alert = ({\n buttonLabel,\n dialogTitle,\n dialogText,\n dialogContent,\n onConfirm = () => {},\n open,\n handleClose,\n cancelButton = false,\n confirmButton = true,\n closeOnClick = true,\n}: AlertProps) => {\n const { t } = useTranslation()\n const classes = useStyles()\n\n const handleSubmit = () => {\n onConfirm()\n handleClose()\n }\n return (\n {\n closeOnClick && handleClose()\n }}>\n
\n {dialogTitle && {dialogTitle}}\n \n {!dialogText ? null : typeof dialogText === 'string' ? (\n {dialogText}\n ) : (\n \n {dialogText.map((text, i) => (\n

{text}

\n ))}\n
\n )}\n {dialogContent && dialogContent}\n
\n \n {cancelButton && (\n \n )}\n {confirmButton && (\n \n )}\n \n
\n \n )\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n dialog: {\n border: 'none',\n },\n dialogTitle: {\n background: theme.palette.blueGray[900],\n color: theme.palette.cyan[500],\n marginBottom: theme.spacing(2),\n },\n })\n)\n\nexport default Alert\n","import { useMutation, useQueryCache } from 'react-query';\nimport { ServerError } from '../types';\nimport { API_URL } from '../constants';\nimport axios from 'axios';\nimport { AlertObject } from './alerts';\n\ntype ReadAlertParams = {\n alerts: string[];\n};\nasync function readAlert({ alerts }: ReadAlertParams) {\n const url = `${API_URL}/alerts/read/`;\n const { data } = await axios.post(url, { alerts }, { withCredentials: true });\n return data.data;\n}\n\nexport function useReadAlert() {\n const queryCache = useQueryCache();\n return useMutation(readAlert, {\n throwOnError: true,\n onMutate: ({ alerts }) => {\n queryCache.cancelQueries('alerts');\n const previousAlerts = queryCache.getQueryData('alerts') as AlertObject[];\n const updatedAlerts = (previousAlerts || []).map((alert) => {\n return alerts.includes(alert._id) ? { ...alert, read: true } : alert;\n });\n //@ts-ignore\n queryCache.setQueryData('alerts', () => updatedAlerts);\n return () => queryCache.setQueryData('alerts', previousAlerts);\n },\n //@ts-ignore\n onError: (err, variables, rollback) => rollback(),\n onSettled: () => {\n queryCache.invalidateQueries('alerts');\n },\n });\n}\n","import { toast, ToastOptions } from 'react-toastify'\nimport makeStyles from '@mui/styles/makeStyles'\nimport React from 'react'\nimport Typography from '@mui/material/Typography'\nimport { faCheck, faCircleExclamation, faTriangleExclamation, faX } from '@fortawesome/pro-light-svg-icons'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nconst useStyles = makeStyles((theme) => ({\n message: {\n display: 'flex',\n justifyContent: 'flex-start',\n alignItems: 'center',\n },\n regularClassName: {\n background: theme.palette.background.paper,\n boxShadow: theme.shadows[1],\n color: theme.palette.text.primary,\n borderRadius: theme.shape.borderRadius,\n },\n regularBodyClassName: {\n padding: theme.spacing(1),\n },\n regularProgressClassName: {\n background: theme.palette.blueGray[900],\n },\n successClassName: {\n background: theme.palette.success.main,\n boxShadow: theme.shadows[1],\n color: theme.palette.common.white,\n borderRadius: theme.shape.borderRadius,\n },\n successBodyClassName: { padding: theme.spacing(0) },\n successProgressClassName: {\n background: theme.palette.common.white,\n },\n errorClassName: {\n background: theme.palette.error.main,\n boxShadow: theme.shadows[1],\n color: theme.palette.common.white,\n borderRadius: theme.shape.borderRadius,\n },\n errorBodyClassName: { padding: theme.spacing(0) },\n errorProgressClassName: {\n background: theme.palette.common.white,\n },\n icon: {\n margin: theme.spacing(0, 1),\n },\n}))\n\nfunction useToast() {\n const classes = useStyles()\n\n const regularMessage = (message) => (\n
\n \n \n {message}\n \n
\n )\n\n const successMessage = (message) => (\n
\n \n \n {message}\n \n
\n )\n\n const errorMessage = (message) => (\n
\n \n \n {message}\n \n
\n )\n\n const regularToast = (message, options?: ToastOptions) =>\n toast(regularMessage(message), {\n className: classes.regularClassName,\n bodyClassName: classes.regularBodyClassName,\n progressClassName: classes.regularProgressClassName,\n closeButton: ,\n ...options,\n })\n\n const toastIdRef = React.useRef()\n\n const progressToast = (message: string, options: ToastOptions) => {\n if (toastIdRef.current === null) {\n toastIdRef.current = toast(regularMessage(message), {\n className: classes.regularClassName,\n bodyClassName: classes.regularBodyClassName,\n progressClassName: classes.regularProgressClassName,\n onClose: () => (toastIdRef.current = null),\n closeButton: ,\n ...options,\n })\n } else {\n toastIdRef.current &&\n toast.update(toastIdRef.current, {\n progress: options.progress,\n })\n }\n }\n\n const successToast = (message, options?: ToastOptions) =>\n toast(successMessage(message), {\n className: classes.successClassName,\n bodyClassName: classes.successBodyClassName,\n progressClassName: classes.successProgressClassName,\n closeButton: ,\n ...options,\n })\n\n const errorToast = (message, options?: ToastOptions) =>\n toast(errorMessage(message), {\n className: classes.errorClassName,\n bodyClassName: classes.errorBodyClassName,\n progressClassName: classes.errorProgressClassName,\n closeButton: ,\n ...options,\n })\n\n return { regularToast, successToast, errorToast, progressToast }\n}\n\nexport default useToast\n","import createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport { IconButton, Typography } from '@mui/material'\nimport { faX } from '@fortawesome/pro-solid-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport moment from 'moment'\nimport { AlertObject } from '../../../../api/alerts/alerts'\nimport { useReadAlert } from '../../../../api/alerts/read-alert'\nimport { useTranslation } from 'react-i18next'\nimport useToast from '../../../hooks/useToast'\n\ntype AlertProps = {\n alert: AlertObject\n}\n\nexport default function Alert({ alert }: AlertProps) {\n const classes = useStyles()\n const [readAlert] = useReadAlert()\n const { t } = useTranslation()\n const { errorToast } = useToast()\n\n async function handleReadAlert(_id: string) {\n try {\n await readAlert({ alerts: [_id] })\n } catch (e) {\n errorToast(t('dashboard.alerts.errors.failedToReadAlert'))\n }\n }\n\n return (\n
\n
\n
\n {alert.title}\n handleReadAlert(alert._id)}>\n \n \n
\n {alert.message} \n
\n \n {moment.unix(alert.alert_time).format('LT DD/MM/YY')}\n \n
\n
\n
\n )\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n root: {\n marginBottom: theme.spacing(2),\n },\n card: {\n textAlign: 'left',\n width: '100%',\n padding: theme.spacing(2, 2, 1, 2),\n borderRadius: theme.shape.borderRadius,\n border: `1px solid ${theme.palette.divider}`,\n },\n cardHeader: {\n width: '100%',\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n },\n cardFooter: {\n width: '100%',\n display: 'flex',\n justifyContent: 'flex-end',\n },\n button: {\n height: 20,\n width: 20,\n },\n })\n)\n","import axios from \"axios\";\nimport { API_URL } from \"../constants\";\nimport { useQuery } from \"react-query\";\nimport { ServerError } from \"../types\";\n\nexport type AlertObject = {\n _id: string;\n title: string;\n message: string;\n alert_time: number;\n read: boolean;\n client_id: string;\n icon: string;\n};\n\nasync function getAlerts() {\n const url = `${API_URL}/alerts/`;\n const { data } = await axios.get(url, { withCredentials: true });\n return data.data;\n}\n\nexport function useGetAlerts() {\n return useQuery(\"alerts\", getAlerts);\n}\n","import { useMutation, useQueryCache } from 'react-query';\nimport { ServerError } from '../types';\nimport { API_URL } from '../constants';\nimport axios from 'axios';\nimport { AlertObject } from './alerts';\n\nasync function readAllAlerts() {\n const url = `${API_URL}/alerts/read_all`;\n const { data } = await axios.post(url, {}, { withCredentials: true });\n return data.data;\n}\n\nexport function useReadAllAlerts() {\n const queryCache = useQueryCache();\n return useMutation(readAllAlerts, {\n throwOnError: true,\n onMutate: (_id) => {\n queryCache.cancelQueries('alerts');\n const previousAlerts = queryCache.getQueryData('alerts') as AlertObject[];\n const updatedAlert = (previousAlerts || []).map((alert) => ({ ...alert, read: true }));\n queryCache.setQueryData('alerts', updatedAlert);\n return () => queryCache.setQueryData('alerts', previousAlerts || []);\n },\n //@ts-ignore\n onError: (err, variables, rollback) => rollback(),\n onSettled: () => {\n queryCache.invalidateQueries('alerts');\n },\n });\n}\n","import { useMemo } from 'react'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport { Badge, Button, Drawer, IconButton, ListItemText, Typography, ButtonBase, ListItem } from '@mui/material'\nimport Alert from './Alert'\nimport { useGetAlerts } from '../../../../api/alerts/alerts'\nimport { useTranslation } from 'react-i18next'\nimport { useReadAllAlerts } from '../../../../api/alerts/read-all-alerts'\nimport useToast from '../../../hooks/useToast'\n\nimport { faBell } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { theme } from '@/theme/theme'\n\ntype AlertPanelProps = {\n open: boolean\n handleClose: () => void\n handleOpen: () => void\n}\n\nexport default function AlertPanel({ open, handleClose, handleOpen }: AlertPanelProps) {\n const classes = useStyles()\n const { t } = useTranslation()\n const { data: alerts } = useGetAlerts()\n const [readAll] = useReadAllAlerts()\n const { errorToast } = useToast()\n const unreadAlerts = useMemo(() => {\n return alerts && alerts.length ? alerts.filter((alert) => !alert.read) : []\n }, [alerts])\n\n async function handleReadAll() {\n try {\n await readAll()\n } catch (e) {\n errorToast(t('dashboard.alerts.errors.failedToReadAll'))\n }\n }\n\n return (\n <>\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n {t('dashboard.alerts.alerts')}\n \n
\n
\n {unreadAlerts && unreadAlerts?.length > 0 ? (\n unreadAlerts.map((alert) => )\n ) : (\n
\n \n {t('dashboard.alerts.noAlerts')}\n \n
\n )}\n
\n
\n \n \n )\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n drawerPaper: {\n width: 350,\n },\n icon: {\n color: theme.palette.common.white,\n marginLeft: theme.spacing(1.5),\n },\n text: {\n marginLeft: theme.spacing(2),\n color: theme.palette.common.white,\n },\n iconWrapper: {\n fontSize: 28,\n width: 64,\n margin: 0,\n marginLeft: 0,\n },\n flex: {\n padding: 2,\n // marginLeft: theme.spacing(1),\n color: theme.palette.common.white,\n textTransform: 'capitalize',\n '&:hover': {\n background: 'transparent',\n },\n },\n list: {\n width: '100%',\n padding: theme.spacing(2, 3),\n },\n listHeader: {\n width: '100%',\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n listBody: {\n paddingTop: theme.spacing(4),\n width: '100%',\n height: '100%',\n },\n emptyList: {\n width: '100%',\n padding: theme.spacing(6, 2),\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n borderRadius: theme.shape.borderRadius,\n border: `1px solid ${theme.palette.divider}`,\n },\n })\n)\n","import axios from \"axios\";\nimport { API_URL } from \"../constants\";\nimport { useMutation, useQueryCache } from \"react-query\";\n\nasync function logout() {\n const url = `${API_URL}/auth/logout/`;\n await axios.post(url, {}, { withCredentials: true });\n}\n\nexport function useLogout() {\n const queryCache = useQueryCache();\n return useMutation(logout, {\n onSuccess: () => {\n queryCache.invalidateQueries();\n queryCache.clear();\n },\n });\n}\n","import React, { useCallback, useMemo, useState } from \"react\";\nimport Lottie from \"react-lottie\";\n\ntype LottieConfig = {\n loop: boolean;\n autoplay: boolean;\n animationData: any;\n rendererSettings: {\n preserveAspectRatio: string;\n };\n};\ntype LottieProps = {\n animationData: any;\n options?: LottieConfig;\n height?: number;\n width?: number;\n};\n\nexport default function UseLottie({\n animationData,\n options,\n height,\n width,\n}: LottieProps) {\n const defaultOptions = useMemo(\n () => ({\n loop: true,\n autoplay: true,\n animationData: animationData,\n rendererSettings: {\n preserveAspectRatio: \"xMidYMid slice\",\n },\n }),\n [animationData]\n );\n\n const [isPaused, setIsPaused] = useState(false);\n const [isStopped, setIsStopped] = useState(false);\n\n const handlePlay = useCallback(() => {\n setIsStopped(false);\n setIsPaused(false);\n }, []);\n\n const handleStop = useCallback(() => {\n setIsStopped(true);\n }, []);\n\n const handlePause = useCallback(() => {\n setIsPaused(!isPaused);\n }, [isPaused]);\n\n const LottieAnimation = useMemo(() => {\n return (\n
\n \n
\n );\n }, [options, defaultOptions, height, width, isStopped, isPaused]);\n\n return { handlePause, handlePlay, handleStop, LottieAnimation } as const;\n}\n","import useLottie from '@/common/hooks/useLottie'\nimport darkAnimationData from '@/assets/lottie/darkNewLabel.json'\nimport lightAnimationData from '@/assets/lottie/lightNewLabel.json'\nimport { CSSProperties } from 'react'\n\ntype NewLabelAnimationProps = {\n style?: CSSProperties\n isDark?: boolean\n size?: number\n}\nconst NewLabelAnimation = ({ style, isDark, size }: NewLabelAnimationProps) => {\n const { LottieAnimation } = useLottie({\n animationData: isDark ? darkAnimationData : lightAnimationData,\n height: size || 50,\n width: size ? 1.5 * size : 100,\n })\n\n return
{LottieAnimation}
\n}\nexport default NewLabelAnimation\n","export const sanitizeString = (input: string | undefined | null): string => {\n if (\n !input ||\n input.trim() === \"\" ||\n input === \"undefined\" ||\n input === \"null\"\n ) {\n return \"\";\n }\n return input;\n};\n","export enum OrganizationAccountType {\n client = 'client',\n direct_reseller = 'direct_reseller',\n indirect_reseller = 'indirect_reseller',\n distributor = 'distributor',\n}\n\nexport enum OrganizationState {\n trial = 'trial',\n subscribed = 'subscribed',\n suspended = 'suspended',\n archived = 'archived',\n}\n\ntype OrganizationDomain = {\n domain: string\n verified: boolean\n}\n\nexport type OrganizationListItem = {\n _id: string\n parent_id: string\n admin: string\n state: OrganizationState\n last_login: string\n name: string\n logo: string\n awareness_score: number\n type: OrganizationAccountType\n origin_country: string\n is_admin_authorized: boolean\n domain: OrganizationDomain\n active_members: number\n total_active_members: number\n number_of_children: number\n created_at: string\n}\n\nexport type OrganizationRequest = {\n parent_id: string\n name: string\n admin_email?: string\n type: OrganizationAccountType\n domain?: string\n admin_name?: string\n allow_support_admin_access?: boolean\n}\n\nexport type OrganizationAcceptInviteRequest = {\n token: string\n}\n\ntype OrganizationUpdateParams = {\n name: string\n domain?: string\n admin_email?: string\n type?: OrganizationAccountType\n allow_support_admin_access?: boolean\n}\n\nexport type OrganizationUpdateRequest = {\n id: string\n params: OrganizationUpdateParams\n}\n\nexport type OrganizationIndustry = {\n id: string\n slug: string\n}\n\nexport type OrganizationOnboardingStatus = {\n organization_details_completed: boolean\n domain_verification_completed: boolean\n allowlisting_completed: boolean\n recipients_management_completed: boolean\n recipients_completed: {\n office_set_up: boolean\n members_added: boolean\n groups_added: boolean\n }\n}\n","import { FC } from 'react'\nimport { Tooltip } from '@mui/material'\n\ninterface TruncatedTextProps {\n text: string\n maxLength?: number\n}\n\nconst TruncatedText: FC = ({ text, maxLength = 15 }) => {\n const isTruncated = text.length > maxLength\n const truncatedText = isTruncated ? `${text.slice(0, maxLength)}...` : text\n\n return isTruncated ? (\n \n {truncatedText}\n \n ) : (\n {truncatedText}\n )\n}\n\nexport default TruncatedText\n","import { faChevronDown, faChevronUp } from '@fortawesome/pro-solid-svg-icons'\nimport { faChartNetwork, faFingerprint, faArrowRightFromBracket } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport {\n Avatar,\n Box,\n Button,\n Divider,\n ListItem,\n ListItemText,\n MenuItem,\n Popover,\n Skeleton,\n Typography,\n} from '@mui/material'\nimport { useTheme } from '@mui/material/styles'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport { FC, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport useMeasure from 'react-use-measure'\n\nimport { useLogout } from '@/api/auth/logout'\nimport { useClientDetails } from '@/api/client/client'\nimport NewLabelAnimation from '@/common/animations/NewLabelAnimation'\nimport { sanitizeString } from '@/common/utils/sanitizeString'\nimport { useAuth } from '@/context/Auth'\nimport { OrganizationAccountType } from '@/types/organizations'\nimport TruncatedText from '../TruncatedText/TruncatedText'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport useNavigateWithLayoutBlocker from '@/common/hooks/useNavigateWithLayoutBlocker'\n\ninterface ProfileButtonProps {\n firstName: string\n}\n\nconst ProfileButton: FC = ({ firstName = '' }) => {\n const classes = useStyles()\n\n return {firstName.charAt(0).toUpperCase()}\n}\n\nconst Dropdown: FC = () => {\n const classes = useStyles()\n const { t } = useTranslation()\n const navigateTo = useNavigateWithLayoutBlocker()\n const { user } = useAuth()\n const { data: client } = useClientDetails()\n const [ref, { width }] = useMeasure()\n const theme = useTheme()\n const [logout] = useLogout()\n const [anchorElement, setAnchorElement] = useState(null)\n\n const handleClick = (event) => {\n event.stopPropagation()\n setAnchorElement(event.currentTarget)\n }\n\n const handleClose = () => {\n setAnchorElement(null)\n }\n\n const handleMyProfile = () => {\n navigateTo(`/settings/admins/${user?.id}`)\n setAnchorElement(null)\n }\n async function handleLogout() {\n await logout()\n navigateTo('/sign-in')\n }\n return (\n <>\n }\n endIcon={\n \n \n \n \n }\n size={'large'}\n variant={'text'}\n aria-haspopup=\"true\"\n onClick={handleClick}\n aria-label={'dropdown menu'}>\n {client || user ? (\n \n \n }\n secondary={}\n secondaryTypographyProps={{\n style: { color: theme.palette.white },\n }}\n />\n \n ) : (\n \n )}\n \n \n \n \n \n {t('navbar.myProfile')}\n \n \n \n {user?.has_multiple_clients || client?.type !== OrganizationAccountType.client ? (\n <>\n navigateTo('/account-center')}>\n \n {t('navbar.accountCenter')}\n \n \n \n ) : null}\n \n \n {t('navbar.signOut')}\n \n \n \n \n )\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n profile: {\n padding: 0,\n paddingRight: theme.spacing(2),\n color: theme.palette.common.white,\n textTransform: 'capitalize',\n '&:hover': {\n background: 'transparent',\n },\n },\n listItemWrapper: {\n width: '134px',\n paddingBottom: 0,\n paddingLeft: theme.spacing(2),\n },\n menuItem: {\n minWidth: 180,\n display: 'flex',\n alignItems: 'center',\n color: theme.palette.text.primary,\n },\n logout: {\n color: theme.palette.error.main,\n },\n icon: {\n fontSize: '28px !important',\n width: 64,\n margin: 0,\n marginLeft: 0,\n },\n iconFa: {\n fontSize: '18px !important',\n },\n avatar: {\n width: 34,\n height: 34,\n backgroundColor: theme.palette.cyan[500],\n color: theme.palette.common.black,\n border: '1px solid white',\n marginLeft: theme.spacing(2),\n },\n iconsWrpper: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n paddingTop: '17px',\n },\n })\n)\nexport default Dropdown\n","import { ListItem, ListItemIcon, ListItemText } from '@mui/material'\nimport { Theme, useTheme } from '@mui/material/styles'\n\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\n\ntype MenuItemProps = {\n onClick: () => void\n selected: boolean\n text: string\n children: React.ReactNode\n}\nexport default function MenuItem({ onClick, selected, text, children }: MenuItemProps) {\n const classes = useStyles()\n const theme = useTheme()\n\n return (\n \n {children}\n \n \n )\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n icon: {\n display: 'flex',\n fontSize: '20px',\n justifyContent: 'space-around',\n color: 'inherit',\n marginRight: '20px',\n },\n })\n)\n","import { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport {\n faBookOpen,\n faBullhorn,\n faChevronLeft,\n faChevronRight,\n faFlag,\n faGear,\n faRectanglesMixed,\n faShieldKeyhole,\n faUserGroupSimple,\n} from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Drawer, IconButton, Link, List } from '@mui/material'\nimport { Theme } from '@mui/material/styles'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport { useContext, useEffect, useState } from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\nimport { useLocation } from 'react-router-dom'\n\nimport LogoIcon from '@/assets/images/logo-clean-blue.svg'\nimport useNavigateWithLayoutBlocker from '@/common/hooks/useNavigateWithLayoutBlocker'\nimport Alert from '../Alert/Alert'\nimport AlertPanel from '../Navbar/AlertPanel/AlertPanel'\nimport Dropdown from '../Navbar/Dropdown'\nimport { LayoutContext } from './Layout'\nimport MenuItem from './MenuItem'\n\nconst Menu = () => {\n const classes = useStyles()\n const navigateTo = useNavigateWithLayoutBlocker()\n const { pathname } = useLocation()\n const { t } = useTranslation()\n const [alertIsOpen, setAlertIsOpen] = useState(false)\n const { isMenuOpen, setIsMenuOpen, menuExpandEnabled, setWasMenuOpen } = useContext(LayoutContext)\n const [alertDrawerIsOpen, setAlertDrawerIsOpen] = useState(false)\n\n // handle sidebar open/close between sessions\n useEffect(() => {\n const storedValue = localStorage.getItem('cw_isSidebarOpen')\n if (storedValue) {\n const parsedStoredValue = JSON.parse(storedValue)\n setIsMenuOpen(parsedStoredValue)\n setWasMenuOpen(parsedStoredValue)\n }\n }, [])\n\n function openAlertDrawer() {\n setAlertDrawerIsOpen(true)\n }\n\n function closeAlertDrawer() {\n setAlertDrawerIsOpen(false)\n }\n const handleToggleSidebar = () => {\n const newState = !isMenuOpen\n setIsMenuOpen(newState)\n setWasMenuOpen(newState)\n localStorage.setItem('cw_isSidebarOpen', JSON.stringify(newState))\n }\n\n function closeAlert() {\n setAlertIsOpen(false)\n }\n\n return (\n <>\n \n To enable, please contact us at\n \n hello@cywareness.io\n \n or via our contact page at\n \n https://cywareness.io/contact-us/\n \n \n }\n />\n \n {'Cywareness\n
\n
\n
\n \n navigateTo('/')} selected={pathname === '/'} text={t('menu.dashboard')}>\n \n \n navigateTo('/content-library')}\n selected={pathname.startsWith('/content-library')}\n text={t('menu.library')}>\n \n \n navigateTo('/campaigns')}\n selected={pathname.startsWith('/campaign') || pathname.startsWith('/training-campaigns')}\n text={t('menu.simulator')}>\n \n \n navigateTo('/response-console')}\n selected={pathname.startsWith('/response-console')}\n text={t('menu.reports')}>\n \n \n \n
\n
\n \n
\n navigateTo('/recipients/members')}\n selected={pathname.includes('/recipients')}\n text={t('menu.users')}>\n \n \n navigateTo('/client-activity')}\n selected={pathname === '/client-activity'}\n text={t('menu.clientActivity')}>\n \n \n navigateTo('/settings')}\n selected={pathname.startsWith('/settings')}\n text={t('menu.settings')}>\n \n \n \n
\n \n
\n
\n
\n
\n \n \n \n
\n
\n \n \n )\n}\n\nconst DRAWER_WIDTH = 250\nconst useStyles = makeStyles((theme) =>\n createStyles({\n toolbarIcon: {\n display: 'flex',\n alignItems: 'center',\n padding: theme.spacing(0, 2),\n marginBottom: theme.spacing(2),\n cursor: 'pointer',\n },\n logo: {\n marginRight: theme.spacing(2),\n position: 'absolute',\n bottom: -50,\n left: -50,\n opacity: 0.2,\n },\n chip: {\n transform: 'scale(0.75) translateX(40px) ',\n },\n title: {\n color: theme.palette.common.white,\n marginLeft: theme.spacing(3),\n },\n drawerPaper: {\n position: 'relative',\n height: '100vh',\n padding: theme.spacing(0, 0.25, 4),\n whiteSpace: 'nowrap',\n boxShadow: theme.shadows[0],\n background: theme.palette.blueGray[900],\n width: DRAWER_WIDTH,\n overflow: 'hidden',\n transition: theme.transitions.create('width', {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.enteringScreen,\n }),\n },\n drawerPaperClose: {\n overflowX: 'hidden',\n transition: theme.transitions.create('width', {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.leavingScreen,\n }),\n width: theme.spacing(8),\n [theme.breakpoints.up('sm')]: {\n width: theme.spacing(8),\n },\n },\n menuPanelWrapper: {\n width: '100%',\n flex: 1,\n },\n menuPanel: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n },\n menuContent: {\n marginTop: theme.spacing(1),\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n overflow: 'hidden',\n alignItems: 'flex-start',\n },\n actionItemsWrapper: {\n marginTop: 20,\n },\n bottomItemsWrapper: {\n width: '100%',\n },\n appIcon: {\n width: 24,\n height: 24,\n color: theme.palette.common.white,\n },\n selected: {\n color: theme.palette.common.white,\n },\n closeMenuIcon: {\n color: theme.palette.common.white,\n float: 'right',\n marginRight: theme.spacing(1),\n },\n })\n)\n\nexport default Menu\n","//old\nexport function serializeArray(array: T[]): Serialized {\n const byId: { [key: string]: T } = {}\n array.forEach((item) => {\n byId[item._id] = item\n })\n return { array, byId }\n}\n\nexport interface Serialized {\n byId: { [key: string]: T }\n array: T[]\n}\n\n//new - reactQueryV5\nexport const paramsSerializer = (params: { [s: string]: unknown } | ArrayLike) => {\n return Object.entries(Object.fromEntries(Object.entries(params).filter(([key, value]) => value !== '')))\n .map(([key, value]) => {\n if (Array.isArray(value)) {\n const arrayValues = value\n .filter((v) => v != null)\n .map((v) => `${encodeURIComponent(key)}=${encodeURIComponent(v as string)}`)\n return arrayValues.length > 0 ? arrayValues.join('&') : ''\n }\n if (value != null) {\n return `${encodeURIComponent(key)}=${encodeURIComponent(value as string)}`\n }\n return ''\n })\n .filter((part) => part !== '')\n .join('&')\n}\n","import { DomainListQuery, DomainsResponse } from '@/types/domains'\nimport { keepPreviousData, useQuery } from '@tanstack/react-query'\nimport axios from 'axios'\n\nimport { API_URL } from '../constants'\nimport { paramsSerializer } from '../utils/serialize-array'\n\nexport async function getDomains(params: DomainListQuery) {\n const url = `${API_URL}/domains/`\n const { data } = await axios.get(url, { withCredentials: true, params, paramsSerializer: paramsSerializer })\n return data\n}\nexport const useDomains = (query: DomainListQuery) => {\n return useQuery({\n queryKey: ['domains', query],\n queryFn: () => {\n return getDomains(query)\n },\n placeholderData: keepPreviousData,\n })\n}\n","export enum SortOrder {\n asc = 'asc',\n desc = 'desc',\n}\n\nexport type PagedResult = {\n total: number\n results: T[]\n}\n\nexport type PagedQuery = {\n skip?: number\n limit?: number\n sort_by?: SortBy\n sort_order?: SortOrder\n}\n\ntype Language = {\n name: string\n nativeName: string\n}\n\nexport type LanguagesByCode = {\n [code: string]: Language\n}\n\n// RowData has either id or _id, but not both\nexport type RowDataItem =\n | ({ id: string; _id?: never } & { [key: string]: any })\n | ({ _id: string; id?: never } & { [key: string]: any })\n","import { PagedQuery } from './common'\n\nexport enum MessageDeliveryType {\n sendgrid = 'sendgrid',\n bridged_delivery = 'bridged_delivery',\n}\n\nexport enum MailboxType {\n gmail = 'gmail',\n exchange_on_prem = 'exchange_on_prem',\n office_365 = 'office_365',\n}\n\nexport type DomainDeliveryConfiguration = {\n message_delivery_type: MessageDeliveryType\n mailbox_type?: MailboxType\n mailbox_host?: string\n mailbox_port?: number\n default: boolean\n enabled: boolean\n spam_filters: DomainSpamFilters\n tls_required?: boolean\n verification_sent_at?: string\n verified: boolean\n}\n\ntype DomainSpamFilters = {\n email_gateway?: boolean\n mail_flow_rules?: boolean\n}\n\nexport type Domain = {\n _id: string\n client_id: string\n domain: string\n verified: boolean\n verify_token: string\n has_members: boolean\n created_at?: string\n message_delivery_configurations: DomainDeliveryConfiguration[]\n}\n\nexport type DomainsQuery = {\n skip: number\n limit: number\n sort_by: string\n sort_order: string\n}\n\nexport type DomainsResponse = {\n total: number\n results: Domain[]\n}\n\nexport enum DomainQuerySort {\n domain = 'domain',\n verified = 'verified',\n created_at = 'created_at',\n}\n\nexport type DomainListQuery = PagedQuery\n\nexport type DomainsRequest = {\n query: DomainsQuery\n}\n","import { ALL_DATA_LIMIT } from '@/api/constants'\nimport { useDomains } from '@/api/domains/get'\nimport CywarenessIcon from '@/assets/images/logo-clean-blue.svg'\nimport useNavigateWithLayoutBlocker from '@/common/hooks/useNavigateWithLayoutBlocker'\nimport { SortOrder } from '@/types/common'\nimport { DomainQuerySort } from '@/types/domains'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faClapperboardPlay, faFishingRod, faUser } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Backdrop, SpeedDial, SpeedDialAction, Typography } from '@mui/material'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\n\nconst INITIAL_QUERY_FILTERS = {\n sort_by: DomainQuerySort.domain,\n sort_order: SortOrder.asc,\n skip: 0,\n limit: ALL_DATA_LIMIT.limit,\n}\n\nexport default function QuickActions() {\n const classes = useStyles()\n const { t } = useTranslation()\n const navigateTo = useNavigateWithLayoutBlocker()\n const { data: domainsData } = useDomains(INITIAL_QUERY_FILTERS)\n const hasVerifiedDomains = domainsData?.results.filter((domain) => domain.verified).length\n const [open, setOpen] = useState(false)\n const handleOpen = () => setOpen(true)\n const handleClose = () => setOpen(false)\n\n const actions = [\n {\n icon: ,\n name: t('quickActions.addUser'),\n action: () => {\n handleClose()\n navigateTo('/recipients/members', { addUser: true })\n },\n disabled: false,\n },\n {\n icon: ,\n name: t('quickActions.createCampaign'),\n action: () => {\n handleClose()\n navigateTo('/content-library/simulations')\n },\n disabled: !hasVerifiedDomains,\n },\n {\n icon: ,\n name: t('quickActions.createTrainingCampaign'),\n action: () => {\n handleClose()\n navigateTo('/content-library/videos')\n },\n disabled: !hasVerifiedDomains,\n },\n ]\n\n return (\n
\n \n }\n onClose={handleClose}\n onOpen={handleOpen}\n open={open}>\n {actions\n .filter((action) => !action.disabled)\n .map((action) => (\n {action.name}}\n tooltipOpen\n onClick={action.action}\n FabProps={{ size: 'medium' }}\n />\n ))}\n \n
\n )\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n root: {\n height: '100vh',\n transform: 'translateZ(0px)',\n flexGrow: 1,\n zIndex: 100,\n },\n speedDial: { position: 'absolute', bottom: 16, right: 16 },\n tooltipLabel: { color: theme.palette.black },\n fab: { color: theme.palette.black },\n })\n)\n","import { createContext, useState } from 'react'\nimport Menu from './Menu'\nimport QuickActions from '../QuickActions/QuickActions'\nimport { useClientDetails } from '@/api/client/client'\nimport { Outlet } from 'react-router-dom'\nimport { PhishingSimulation } from '@/types/phishingSimulations'\nimport useToast from '@/common/hooks/useToast'\nimport { useTranslation } from 'react-i18next'\nimport { Box, styled } from '@mui/material'\nimport { theme } from '@/theme/theme'\n\nconst defaultLayoutContextValues: {\n blockedNavigationRequest: string\n setBlockedNavigationRequest: (e: string) => void\n navigationBlock: boolean\n setNavigationBlock: (e: boolean) => void\n menuExpandEnabled: boolean\n setMenuExpandEnabled: (e: boolean) => void\n isMenuOpen: boolean\n setIsMenuOpen: (e: boolean) => void\n wasMenuOpen: boolean\n setWasMenuOpen: (e: boolean) => void\n tempSimulationPackage: PhishingSimulation[]\n resetSimulationPackage: () => void\n addToSimulationPackage: (simulation: PhishingSimulation) => void\n removeFromSimulationPackage: (index: number) => void\n setTempSimulationPackage: (e: any) => void\n setTempSimulationPackageId: (e: string) => void\n setTempSimulationPackageName: (e: string) => void\n tempSimulationPackageId: string\n tempSimulationPackageName: string\n} = {\n blockedNavigationRequest: '/',\n setBlockedNavigationRequest: (e: string) => {},\n navigationBlock: false,\n setNavigationBlock: (e: boolean) => {},\n menuExpandEnabled: true,\n setMenuExpandEnabled: (e: boolean) => {},\n isMenuOpen: true,\n setIsMenuOpen: (e: boolean) => {},\n wasMenuOpen: true,\n setWasMenuOpen: (e: boolean) => {},\n tempSimulationPackage: [],\n resetSimulationPackage: () => {},\n addToSimulationPackage: (simulation: PhishingSimulation) => {},\n removeFromSimulationPackage: (index: number) => {},\n setTempSimulationPackage: (e: any) => {},\n setTempSimulationPackageId: (e: string) => {},\n setTempSimulationPackageName: (e: string) => {},\n tempSimulationPackageId: '',\n tempSimulationPackageName: '',\n}\n\nexport const LayoutContext = createContext(defaultLayoutContextValues)\n\nexport default function Layout() {\n const [navigationBlock, setNavigationBlock] = useState(false)\n const [blockedNavigationRequest, setBlockedNavigationRequest] = useState('/')\n const [menuExpandEnabled, setMenuExpandEnabled] = useState(true)\n const [isMenuOpen, setIsMenuOpen] = useState(true)\n const [wasMenuOpen, setWasMenuOpen] = useState(true)\n const [tempSimulationPackage, setTempSimulationPackage] = useState([])\n const [tempSimulationPackageId, setTempSimulationPackageId] = useState('')\n const [tempSimulationPackageName, setTempSimulationPackageName] = useState('')\n const { errorToast } = useToast()\n const { t } = useTranslation()\n\n const resetSimulationPackage = () => {\n setTempSimulationPackage([])\n }\n const addToSimulationPackage = (simulation: PhishingSimulation) => {\n if (tempSimulationPackage.map((tempSimulation: PhishingSimulation) => tempSimulation.id).includes(simulation.id)) {\n errorToast(t('simulationPackage.alreadyExist'))\n return\n }\n setTempSimulationPackage((prevPackages: PhishingSimulation[]) => [...prevPackages, simulation])\n }\n\n const removeFromSimulationPackage = (index: number) => {\n setTempSimulationPackage(tempSimulationPackage.slice(0, index - 1).concat(tempSimulationPackage.slice(index)))\n }\n\n const { data: clientDetails, isLoading } = useClientDetails()\n\n return (\n \n \n \n {/* remove the Box after replace all the other pages to use page layout */}\n \n \n \n {!clientDetails?.onboarding && !isLoading ? null : }\n \n \n )\n}\n\nconst StyledLayoutContainer = styled(Box)(() => ({\n display: 'flex',\n position: 'relative',\n overflow: 'hidden',\n height: '100vh',\n background: theme.palette.grey[100],\n}))\n","import { App } from '../../api/apps/apps'\nexport const getAppsObject = (apps: App[]) => {\n const appsObject: {\n [key: string]: App\n } = {}\n apps.forEach((app) => {\n appsObject[app.title.toLowerCase()] = app\n })\n return appsObject\n}\n","import React, { createContext, useState, FC, ReactNode } from 'react'\n\ninterface ContentLibraryState {\n name: string\n languages: string[]\n tags: string[]\n difficulties?: string[]\n vectors?: string[]\n ai_generated?: boolean | null\n is_public?: boolean | null\n package_only?: boolean | null\n}\n\ninterface ContentLibraryContextProps {\n queryFilters: ContentLibraryState\n setQueryFilters: React.Dispatch>\n}\n\nexport const ContentLibraryContext = createContext(undefined)\n\ninterface ContentLibraryProviderProps {\n children: ReactNode\n}\n\nexport const ContentLibraryProvider: FC = ({ children }) => {\n const [queryFilters, setQueryFilters] = useState({\n name: '',\n languages: [],\n tags: [],\n difficulties: [],\n vectors: [],\n })\n\n return (\n \n {children}\n \n )\n}\n","import Axios from 'axios'\nimport { DefinedInitialDataOptions, useQuery } from '@tanstack/react-query'\n\nimport { API_URL } from '@/api/constants'\nimport { OrganizationListItem } from '@/types/organizations'\n\nconst getOrganizations = async () => {\n const url = `${API_URL}/organizations/`\n const { data } = await Axios.get(url, { withCredentials: true })\n\n return data\n}\n\nconst getOrganization = async (id: string) => {\n const url = `${API_URL}/organizations/${id}`\n const { data } = await Axios.get(url, { withCredentials: true })\n\n return data\n}\n\nexport const useOrganizations = (options?: Partial>) =>\n useQuery({\n queryKey: ['organizations'],\n queryFn: getOrganizations,\n ...options,\n })\n\nexport const useOrganization = (id: string, options?: Partial>) =>\n useQuery({\n queryKey: ['organization', id],\n queryFn: () => getOrganization(id),\n ...options,\n })\n","import { FC, ChangeEvent, ReactElement } from 'react'\nimport { useField, FieldHookConfig } from 'formik'\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport MuiCheckbox, { CheckboxProps as MuiCheckboxProps } from '@mui/material/Checkbox'\n\ninterface CheckboxProps extends Omit, Pick, 'name'> {\n label: string | ReactElement\n disableFormik?: boolean\n onChange?: MuiCheckboxProps['onChange']\n}\n\nconst Checkbox: FC = ({ name, label, disableFormik = false, onChange, ...props }) => {\n const [field, , helpers] = useField(name)\n\n const isChecked = disableFormik ? !!props.checked : field.value\n\n const handleChange = (event: ChangeEvent, checked: boolean) => {\n if (!disableFormik) {\n helpers.setValue(checked)\n }\n\n if (onChange) {\n onChange(event, checked)\n }\n }\n\n const configCheckbox: MuiCheckboxProps & { checked: boolean } = {\n ...props,\n disableRipple: true,\n checked: isChecked,\n onChange: handleChange,\n }\n\n return (\n }\n label={label}\n />\n )\n}\n\nexport default Checkbox\n","import React, { FC } from 'react'\nimport { useField, FieldHookConfig } from 'formik'\nimport MuiTextField, { TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField'\n\ninterface TextFieldProps\n extends Omit,\n Pick, 'name'> {\n disableFormik?: boolean\n value?: MuiTextFieldProps['value']\n onChange?: MuiTextFieldProps['onChange']\n onBlur?: MuiTextFieldProps['onBlur']\n}\n\nconst TextField: FC = ({\n name,\n label,\n placeholder,\n InputProps,\n InputLabelProps,\n disableFormik = false,\n onChange,\n onBlur,\n ...otherProps\n}) => {\n const [field, meta] = useField(name)\n\n const combinedInputProps = {\n style: {\n height: '20px',\n padding: '8px 8px 8px 16px',\n },\n ...InputProps,\n }\n\n const combinedInputLabelProps = {\n shrink: true,\n ...InputLabelProps,\n }\n\n const configTextField: MuiTextFieldProps = {\n ...otherProps,\n fullWidth: true,\n label: label,\n placeholder: placeholder,\n InputLabelProps: combinedInputLabelProps,\n inputProps: combinedInputProps as any,\n }\n\n if (!disableFormik) {\n // Merge Formik-related props if Formik is enabled\n Object.assign(configTextField, {\n ...field,\n error: meta.touched && Boolean(meta.error),\n helperText: meta.touched && meta.error,\n onChange: onChange\n ? (event) => {\n field.onChange(event)\n onChange(event)\n }\n : field.onChange,\n onBlur: onBlur\n ? (event) => {\n field.onBlur(event)\n onBlur(event)\n }\n : field.onBlur,\n })\n } else {\n // Attach provided onChange and onBlur handlers for non-Formik usage\n if (onChange) configTextField.onChange = onChange\n if (onBlur) configTextField.onBlur = onBlur\n }\n\n return \n}\n\nexport default TextField\n","import Axios from 'axios'\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\n\nimport { API_URL } from '@/api/constants'\nimport { OrganizationRequest } from '@/types/organizations'\n\nconst organizationCreate = async (organizationPayload: OrganizationRequest) => {\n const url = `${API_URL}/organizations/`\n const { data } = await Axios.post(url, organizationPayload, { withCredentials: true })\n\n return data\n}\n\nconst useOrganizationCreate = () => {\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: organizationCreate,\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: ['organizations'],\n })\n },\n })\n}\n\nexport { useOrganizationCreate }\n","export function getErrorMessage(error: any) {\n if (error.response) {\n return error.response.data.message || error.response.data.detail[0].msg\n } else {\n return null\n }\n}\n","import { theme } from '@/theme/theme'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faX } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Box, IconButton, Modal as MuiModal, styled, Typography } from '@mui/material'\nimport { FC, ReactNode } from 'react'\n\ntype ModalSize = 'small' | 'medium' | 'mediumLarge' | 'large'\n\nconst modalSizeMap: Record = {\n small: '432px',\n medium: '640px',\n mediumLarge: '960px',\n large: '1216px',\n}\ninterface ModalProps {\n title: string\n isOpen: boolean\n onClose: () => void\n size?: ModalSize\n withCloseButton?: boolean\n children: ReactNode\n}\n\nconst Modal: FC = ({ title, isOpen, onClose, children, size = 'medium', withCloseButton }) => {\n return (\n \n \n \n {withCloseButton && (\n \n \n \n )}\n \n {title}\n \n \n {children}\n \n \n )\n}\n\nconst StyledModalContent = styled(Box)(({ width }: { width: string }) => ({\n position: 'absolute',\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n width: width,\n backgroundColor: 'white',\n p: 4,\n '&:focus-visible': {\n outline: 'none',\n },\n borderRadius: '10px',\n}))\n\nconst StyledTitleBar = styled(Box)(() => ({\n display: 'flex',\n color: theme.palette.cyan[500],\n alignItems: 'center',\n padding: '10px 16px',\n fontSize: '18px',\n fontStyle: 'normal',\n fontWeight: theme.typography.fontWeightMedium,\n lineHeight: 'normal',\n background: theme.palette.black,\n borderRadius: '10px 10px 0px 0px',\n}))\n\nconst StyledContent = styled(Box)(() => ({\n maxHeight: '90vh',\n overflowY: 'auto',\n margin: '24px 8px 24px 32px',\n padding: '0 24px 0 0', //scroll bar offset\n}))\n\nexport default Modal\n","export default \"__VITE_ASSET__7e94d43c__\"","import { theme } from '@/theme/theme'\nimport { Box, styled } from '@mui/material'\n\nexport const ModalConent = styled(Box)(() => ({\n position: 'absolute',\n top: '40%',\n left: '50%',\n transform: 'translate(-50%, -40%)',\n minWidth: '800px',\n padding: theme.spacing(4),\n display: 'flex',\n backgroundColor: 'white',\n borderRadius: '10px',\n '&:focus-visible': {\n outline: 'none',\n },\n}))\n\nexport const ImageWrapper = styled(Box)(() => ({\n width: '192px',\n height: '192px',\n flexShrink: 0,\n img: {\n width: '100%',\n height: '100%',\n },\n}))\n\nexport const ContentWrapper = styled(Box)(() => ({\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n flex: 1,\n gap: theme.spacing(4),\n}))\n\nexport const StyledTypography = styled(Box)(() => ({\n fontFamily: 'Montserrat',\n fontSize: '16px',\n paddingBottom: theme.spacing(2),\n h4: {\n margin: theme.spacing(0, 0, 2),\n fontSize: '18px',\n fontWeight: 700,\n },\n ul: {\n margin: theme.spacing(0, 0, 0, -2.5),\n '& li::marker': {\n fontSize: '0.7em',\n },\n },\n}))\n\nexport const ButtonsWrapper = styled(Box)(() => ({\n display: 'flex',\n justifyContent: 'flex-end',\n gap: '8px',\n}))\n","import Modal from '@mui/material/Modal'\nimport { FC } from 'react'\nimport { useTranslation } from 'react-i18next'\n\nimport { useOrganizationCreate } from '@/api/organizations/create'\nimport { getErrorMessage } from '@/api/utils/get-error'\nimport inviteImage from '@/assets/images/account-center/invite-image.svg'\nimport useToast from '@/common/hooks/useToast'\nimport { OrganizationListItem, OrganizationRequest } from '@/types/organizations'\nimport { ButtonsWrapper, ContentWrapper, ImageWrapper, ModalConent, StyledTypography } from './PopupsStyledComponents'\nimport { ModalProps } from './TreeChart'\nimport { Button } from '@mui/material'\n\ntype InvitePopupProps = Omit & {\n organizationPayload: OrganizationRequest\n focusNode?: (value: OrganizationListItem | null, collapse?: boolean, highlighted?: boolean) => void\n onClose: () => void\n onCreate: () => void\n}\n\nconst InvitePopup: FC = ({ open, setOpen, organizationPayload, focusNode, onClose, onCreate }) => {\n const { t } = useTranslation()\n const handleClose = () => {\n onClose()\n setOpen(false)\n }\n\n const { mutateAsync: createOrganization } = useOrganizationCreate()\n const { errorToast, successToast } = useToast()\n\n const handleCreate = async (invite = true) => {\n if (!invite) {\n organizationPayload.admin_email = ''\n }\n try {\n const newOrganization = await createOrganization(organizationPayload)\n handleClose()\n onCreate()\n successToast(t('accountCenter.editModal.updateSuccess'))\n setTimeout(() => {\n focusNode && focusNode(newOrganization, false)\n }, 100)\n } catch (e) {\n const errorMessage = getErrorMessage(e)\n errorToast(errorMessage || t('accountCenter.addModal.addFailed'))\n }\n }\n\n return (\n \n \n \n \"invite\"\n \n\n \n \n

{t('accountCenter.invitePopup.title', { email: organizationPayload.admin_email })}

\n

{t('accountCenter.invitePopup.message')}

\n

{t('accountCenter.invitePopup.message2')}

\n
\n\n \n \n {\n handleCreate(false)\n }}>\n {t('accountCenter.invitePopup.submit2')}\n \n \n \n
\n
\n
\n )\n}\n\nexport default InvitePopup\n","import { Box, styled } from '@mui/material'\n\nexport const CheckboxWrapper = styled(Box)(() => ({\n '& span': {\n fontSize: '12px',\n },\n}))\nexport const Lock = styled(Box)(() => ({\n position: 'absolute',\n right: '54px',\n transform: 'translate(0px, -30px)',\n}))\n\nexport const FieldsWrapper = styled(Box)(() => ({\n display: 'flex',\n gap: 16,\n flexDirection: 'column',\n}))\nexport const ButtonsWrapper = styled(Box)(() => ({\n padding: '0px 20px 10px',\n display: 'flex',\n gap: 40,\n flexDirection: 'row',\n justifyContent: 'center',\n}))\n","import Checkbox from '@/common/components/Inputs/Checkbox'\nimport TextField from '@/common/components/Inputs/TextField'\nimport { Box, Button, Typography, styled } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { FC, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport useToast from '../../hooks/useToast'\n\nimport { DOMAIN_REGEX } from '@/api/constants'\nimport { useOrganizationCreate } from '@/api/organizations/create'\nimport { getErrorMessage } from '@/api/utils/get-error'\nimport { OrganizationAccountType, OrganizationRequest } from '@/types/organizations'\n//@ts-ignore\nimport * as Yup from 'yup'\nimport Modal from '../Modal'\nimport InvitePopup from './InvitePopup'\nimport { ButtonsWrapper, CheckboxWrapper, FieldsWrapper } from './ModalStyledComponents'\nimport { ModalProps } from './TreeChart'\n\nconst AddModal: FC = ({ open, setOpen, organization, focusNode }) => {\n const { t } = useTranslation()\n const [afterClick, setAfterClick] = useState(false)\n const [backFromInvite, setBackFromInvite] = useState(false)\n const [initialValues, setInitialValues] = useState({\n email: '',\n adminName: '',\n organizationName: '',\n domain: '',\n allowAdd: false,\n allowSuportAdminAccess: false,\n })\n const [organizationPayload, setOrganizationPayload] = useState({\n parent_id: organization.id,\n name: '',\n type: OrganizationAccountType.client,\n })\n\n const { successToast, errorToast } = useToast()\n const { mutateAsync: createOrganization } = useOrganizationCreate()\n const handleClose = () => {\n setOpen(false)\n }\n\n const resetCreate = () => {\n setBackFromInvite(false)\n }\n\n const handleAdd = async (values: {\n adminName: string\n email: string\n organizationName: string\n domain: string\n allowAdd: boolean\n allowSuportAdminAccess: boolean\n }) => {\n const payload = {\n parent_id: organization.id,\n name: values.organizationName,\n admin_email: values.email,\n type: values.allowAdd ? OrganizationAccountType.indirect_reseller : OrganizationAccountType.client,\n domain: values.domain,\n admin_name: values.adminName,\n allow_support_admin_access: values.allowSuportAdminAccess,\n }\n\n try {\n if (values.email) {\n setInitialValues(values)\n setOrganizationPayload(payload)\n setAfterClick(true)\n } else {\n const newOrganization = await createOrganization(payload)\n handleClose()\n successToast(t('accountCenter.addModal.addSuccessful'))\n setTimeout(() => {\n focusNode && focusNode(newOrganization, false)\n }, 100)\n }\n } catch (e) {\n const errorMessage = getErrorMessage(e)\n errorToast(errorMessage || t('accountCenter.addModal.addFailed'))\n }\n }\n\n const validationSchema = Yup.object().shape({\n adminName: Yup.string().test(\n 'adminName-required-if-email',\n t('accountCenter.addModal.adminNameRequired'),\n function (this: Yup.TestContext, value: string | undefined) {\n const { email } = this.parent\n if (email && email.length > 0) {\n return !!value\n }\n return true\n }\n ),\n email: Yup.string()\n .email(t('accountCenter.addModal.emailInvalid'))\n .test(\n 'email-required-if-adminName',\n t('accountCenter.addModal.emailRequired'),\n function (this: Yup.TestContext, value: string | undefined) {\n const { adminName } = this.parent\n if (adminName && adminName.length > 0) {\n return !!value\n }\n return true\n }\n ),\n organizationName: Yup.string()\n .min(2, t('accountCenter.addModal.tooShort'))\n .max(50, t('accountCenter.addModal.tooLong'))\n .required(t('accountCenter.addModal.organizationNameRequired')),\n domain: Yup.string()\n .matches(DOMAIN_REGEX, t('accountCenter.addModal.domainWarning'))\n .required(t('accountCenter.addModal.domainWarning')),\n allowAdd: Yup.boolean(),\n })\n\n return (\n <>\n {!afterClick ? (\n \n \n \n {({ isSubmitting, values, isValid, dirty, errors }) => (\n
\n \n \n \n {!errors.adminName && (\n \n {t('accountCenter.addModal.notReqired')}\n \n )}\n \n \n \n {!errors.email && (\n \n {t('accountCenter.addModal.inviteWillBeSent')}\n \n )}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n {t('accountCenter.addModal.submit')}\n \n \n
\n )}\n
\n
\n
\n ) : (\n setAfterClick(false)}\n onClose={() => {\n setBackFromInvite(true)\n }}\n onCreate={handleClose}\n organizationPayload={organizationPayload}\n focusNode={focusNode}\n />\n )}\n \n )\n}\n\nconst StyledFieldBox = styled(Box)(() => ({\n height: '50px',\n}))\n\nexport default AddModal\n","import Axios from 'axios'\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\n\nimport { API_URL } from '@/api/constants'\nimport { OrganizationAcceptInviteRequest, OrganizationUpdateRequest } from '@/types/organizations'\n\nconst organizationAcceptInvite = async (token: OrganizationAcceptInviteRequest) => {\n const url = `${API_URL}/organizations/accept-invitation/`\n const { data } = await Axios.post(url, { token }, { withCredentials: true })\n\n return data\n}\n\nconst organizationUpdate = async ({ id, params }: OrganizationUpdateRequest) => {\n const url = `${API_URL}/organizations/${id}`\n const { data } = await Axios.patch(url, params, { withCredentials: true })\n\n return data\n}\n\nconst organizationArchive = async ({ id }: { id: string }) => {\n const url = `${API_URL}/organizations/archive/${id}`\n const { data } = await Axios.put(url, {}, { withCredentials: true })\n\n return data\n}\n\nconst useOrganizationAcceptInvite = () => {\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: organizationAcceptInvite,\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: ['organizations'],\n })\n },\n })\n}\n\nconst useOrganizationUpdate = () => {\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: organizationUpdate,\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: ['organizations'],\n })\n },\n })\n}\n\nconst useOrganizationArchive = () => {\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: organizationArchive,\n onSuccess: () => {\n // do not rerender before react updates (setTimeOut)\n setTimeout(() => {\n queryClient.invalidateQueries({\n queryKey: ['organizations'],\n })\n }, 1)\n },\n })\n}\n\nexport { useOrganizationAcceptInvite, useOrganizationUpdate, useOrganizationArchive }\n","export default \"__VITE_ASSET__5a30262c__\"","import LoadingButton from '@mui/lab/LoadingButton'\nimport { Box, Button } from '@mui/material'\nimport Modal from '@mui/material/Modal'\nimport { FC, ReactNode, useState } from 'react'\n\nimport { ButtonsWrapper, ImageWrapper, ModalConent, StyledTypography } from '../AccountCenter/PopupsStyledComponents'\n\ntype PopupProps = {\n open: boolean\n onClose: () => void\n onConfirm?: (params?: any) => void\n buttonLabels?: { confirm?: string; cancel?: string }\n icon: string\n children: ReactNode[] | ReactNode\n disableBackdropClick?: boolean\n extraBottom?: ReactNode[] | ReactNode\n}\n\nconst Popup: FC = ({\n open,\n onClose,\n onConfirm,\n buttonLabels,\n icon,\n children,\n disableBackdropClick,\n extraBottom,\n}) => {\n const [isPending, setIsPending] = useState(false)\n\n const handleClose = (_: React.SyntheticEvent, reason: 'backdropClick') => {\n if (reason === 'backdropClick' && disableBackdropClick) {\n return\n }\n setIsPending(false)\n onClose()\n }\n\n const handleConfirm = async () => {\n setIsPending(true)\n try {\n if (onConfirm) await onConfirm()\n } catch (e) {\n setIsPending(false)\n throw e\n }\n setIsPending(false)\n }\n\n return (\n \n \n \n \n \"invite\"\n \n {children}\n \n {extraBottom && {extraBottom}}\n \n {!!buttonLabels?.cancel && (\n \n )}\n {Boolean(onConfirm) && (\n \n {buttonLabels?.confirm}\n \n )}\n \n \n \n )\n}\n\nexport default Popup\n","import dayjs from 'dayjs'\nimport { FC } from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\n\nimport { US_DATE_WITH_MONTH_NAME } from '@/api/constants'\nimport { useOrganizationArchive } from '@/api/organizations/update'\nimport { getErrorMessage } from '@/api/utils/get-error'\nimport questionImg from '@/assets/images/popup/question.svg'\nimport useToast from '@/common/hooks/useToast'\nimport Popup from '../Popup'\nimport { ModalProps } from './TreeChart'\n\nconst ArchivePopup: FC = ({ open, setOpen, organization }) => {\n const { t } = useTranslation()\n const { mutateAsync: archiveOrganization } = useOrganizationArchive()\n const { errorToast, successToast } = useToast()\n\n const handleArchive = async () => {\n try {\n await archiveOrganization({ id: organization.id })\n setOpen(false)\n successToast(t('accountCenter.archivePopup.success'))\n } catch (e) {\n const errorMessage = getErrorMessage(e)\n errorToast(errorMessage)\n }\n }\n return (\n {\n setOpen(false)\n }}\n onConfirm={handleArchive}\n buttonLabels={{\n confirm: t('accountCenter.archivePopup.archive'),\n cancel: t('accountCenter.archivePopup.cancel'),\n }}\n icon={questionImg}\n extraBottom={\n , 2:
    , 3:
  • }}>\n }>\n , 2:

    , 3: , 4:

      , 5:
    • }}\n values={{\n state: t('accountCenter.archivePopup.state.' + organization.state),\n lastSignIn: organization.last_login\n ? dayjs.utc(organization.last_login).format(US_DATE_WITH_MONTH_NAME)\n : t('accountCenter.archivePopup.none'),\n }}>\n \n )\n}\n\nexport default ArchivePopup\n","import { useMutation as useMutation5, useQueryClient } from '@tanstack/react-query'\nimport axios from 'axios'\nimport { useMutation, useQueryCache } from 'react-query'\nimport { API_URL } from '../constants'\n\nasync function switchClient(client_id: string) {\n await axios.post(`${API_URL}/profile/change-client/`, { client_id }, { withCredentials: true })\n}\n\nexport function useSwitchClient() {\n const queryCache = useQueryCache()\n return useMutation(switchClient, {\n onSuccess: async () => {\n await queryCache.invalidateQueries()\n queryCache.clear()\n },\n })\n}\n\nexport const useSwitchClientV5 = () => {\n const queryClient = useQueryClient()\n const queryCache = useQueryCache()\n\n return useMutation5({\n mutationFn: switchClient,\n onSuccess: async () => {\n await queryCache.invalidateQueries()\n await queryClient.invalidateQueries({\n queryKey: ['organizations'],\n })\n await queryClient.invalidateQueries({\n queryKey: ['admins'],\n })\n },\n })\n}\n","export default \"__VITE_ASSET__3f8a2939__\"","export default \"__VITE_ASSET__c0da2db1__\"","import { Dispatch, FC, SetStateAction } from 'react'\nimport { useTranslation } from 'react-i18next'\n\nimport { useSwitchClientV5 } from '@/api/profile/switch-client'\nimport { getErrorMessage } from '@/api/utils/get-error'\nimport noPermissionImg from '@/assets/images/account-center/no-permissions.svg'\nimport switchAccountImg from '@/assets/images/account-center/switch-account.svg'\nimport useToast from '@/common/hooks/useToast'\nimport Popup from '../Popup'\nimport { OrganizationCardData } from '@/pages/AccountCenter'\n\ntype ClientSwitchPopupProps = {\n open: boolean\n setOpen: Dispatch>\n organization: OrganizationCardData\n}\n\nconst ClientSwitchPopup: FC = ({ open, setOpen, organization }) => {\n const { t } = useTranslation()\n const { errorToast } = useToast()\n const { mutateAsync: switchClient } = useSwitchClientV5()\n\n const handleClose = () => {\n setOpen(false)\n }\n\n const handleLogin = async () => {\n try {\n await switchClient(organization.id)\n window.location.href = '/'\n } catch (e) {\n const errorMessage = getErrorMessage(e)\n errorToast('Login error ' + errorMessage || '')\n }\n }\n if (organization?.is_admin_authorized)\n return (\n \n

      {t('accountCenter.clientSwtichPopup.title')}

      \n

      {t('accountCenter.clientSwtichPopup.message', { organizationName: organization.name })}

      \n \n )\n return (\n \n

      {t('accountCenter.clientSwtichPopup.noPermissionsTitle')}

      \n {t('accountCenter.clientSwtichPopup.noPermissionsMessage')}\n \n )\n}\n\nexport default ClientSwitchPopup\n","import useLottie from '@/common/hooks/useLottie'\n\nimport animationData from '@/assets/lottie/fingerprint.json'\nimport { Box, styled } from '@mui/material'\n\nconst LoadingAnimation = ({ size = 15 }: { size?: number }) => {\n const { LottieAnimation } = useLottie({\n animationData: animationData,\n height: size * 20,\n width: size * 20,\n })\n\n return {LottieAnimation}\n}\nconst Container = styled(Box)(() => ({\n position: 'absolute',\n top: 0,\n display: 'flex',\n width: '100%',\n height: '100%',\n justifyContent: 'center',\n alignItems: 'center',\n}))\n\nexport default LoadingAnimation\n","import Checkbox from '@/common/components/Inputs/Checkbox'\nimport TextField from '@/common/components/Inputs/TextField'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faLock } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Box, Button, Popover, Typography, styled } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { FC, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\n//@ts-ignore\nimport * as Yup from 'yup'\n\nimport { DOMAIN_REGEX } from '@/api/constants'\nimport { useOrganizationUpdate } from '@/api/organizations/update'\nimport { getErrorMessage } from '@/api/utils/get-error'\nimport useToast from '@/common/hooks/useToast'\nimport { OrganizationAccountType } from '@/types/organizations'\nimport LoadingAnimation from '../MobilePhonePreview/LoadingAnimation'\nimport Modal from '../Modal'\nimport { ButtonsWrapper, CheckboxWrapper, FieldsWrapper } from './ModalStyledComponents'\nimport { ModalProps } from './TreeChart'\n\nconst EditModal: FC = ({ open, setOpen, organization }) => {\n const { t } = useTranslation()\n const [anchorEl, setAnchorEl] = useState(null)\n const handlePopoverOpen = (event: React.MouseEvent) => {\n setAnchorEl(event.currentTarget)\n }\n\n const { errorToast, successToast } = useToast()\n const { mutateAsync: editOrganization, isPending } = useOrganizationUpdate()\n\n const handlePopoverClose = () => {\n setAnchorEl(null)\n }\n\n const handleClose = () => {\n setOpen(false)\n }\n\n const handleEdit = async (values: {\n organizationName: string\n domain: string\n domainVerified: boolean\n allowAdd: boolean\n numberOfChildren: number\n allowSuportAdminAccess: boolean\n }) => {\n try {\n await editOrganization({\n id: organization.id,\n params: {\n name: values.organizationName,\n domain: !values.domainVerified ? values.domain : '',\n type: values.allowAdd ? OrganizationAccountType.direct_reseller : OrganizationAccountType.client,\n allow_support_admin_access: values.allowSuportAdminAccess,\n },\n })\n\n handleClose()\n successToast(t('accountCenter.editModal.updateSuccess'))\n } catch (e) {\n const errorMessage = getErrorMessage(e)\n errorToast(errorMessage || t('accountCenter.editModal.updateFailed'))\n }\n }\n\n const popOverOpen = Boolean(anchorEl)\n\n const validationSchema = Yup.object().shape({\n organizationName: Yup.string()\n .min(2, t('accountCenter.editModal.tooShort'))\n .max(50, t('accountCenter.editModal.tooLong'))\n .required(t('accountCenter.editModal.organizationNameRequired')),\n domain: Yup.string()\n .matches(DOMAIN_REGEX, t('accountCenter.editModal.domainWarning'))\n .required(t('accountCenter.editModal.domainWarning')),\n allowAdd: Yup.boolean(),\n })\n\n const initialValues = {\n organizationName: organization.name,\n domain: organization?.domain?.domain,\n domainVerified: organization?.domain?.verified,\n allowAdd: organization.type !== OrganizationAccountType.client,\n numberOfChildren: organization.number_of_children,\n allowSuportAdminAccess: organization.allow_support_admin_access,\n }\n\n return (\n \n \n {isPending && }\n \n {({ values, dirty }) => (\n
      \n \n \n \n \n \n \n {values.domainVerified && (\n \n \n \n )}\n \n \n {t('accountCenter.editModal.cantEdit')}\n
      \n {t('accountCenter.editModal.goSettingPage')}\n
      \n \n
      \n \n \n 0}\n label={t('accountCenter.editModal.allowAdd')}\n checked={values.allowAdd}\n />\n \n \n \n
      \n \n \n \n \n
      \n )}\n
      \n
      \n
      \n )\n}\n\nconst Lock = styled(Box)(() => ({\n position: 'absolute',\n right: '54px',\n transform: 'translate(0px, -30px)',\n}))\n\nexport default EditModal\n","import { theme } from '@/theme/theme'\nimport { Autocomplete, Box, TextField } from '@mui/material'\nimport { createStyles, makeStyles } from '@mui/styles'\nimport { FC } from 'react'\nimport { useTranslation } from 'react-i18next'\n\nimport { useOrganizations } from '@/api/organizations/get'\n\nimport { OrganizationListItem } from '@/types/organizations'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { faMagnifyingGlass } from '@fortawesome/pro-light-svg-icons'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\n\ntype TreeChartSearchProps = {\n searchValue: OrganizationListItem | null\n setSearchValue: (value: OrganizationListItem | null) => void\n handleSearch: (name: OrganizationListItem | null) => void\n handleClose: () => void\n}\n\nconst TreeChartSearch: FC = ({ searchValue, setSearchValue, handleSearch, handleClose }) => {\n const { t } = useTranslation()\n const { data } = useOrganizations()\n const classes = useStyles()\n const handleInputChange = (_: any, newInputValue: string) => {\n if (!newInputValue) {\n handleClose()\n }\n }\n\n return (\n \n {\n setSearchValue(newValue as OrganizationListItem | null)\n handleSearch(newValue as OrganizationListItem | null)\n }}\n onInputChange={handleInputChange}\n freeSolo\n options={(data || []).sort((a, b) => a.name.localeCompare(b.name))}\n getOptionLabel={(option) => (typeof option === 'string' ? option : option.name || '')}\n renderOption={(props, option) => (\n
    • \n {typeof option === 'string' ? option : option.name || ''}\n
    • \n )}\n renderInput={(params) => {\n return (\n \n ),\n }}\n InputLabelProps={{ children: (params.InputLabelProps?.children as React.ReactNode) || null }}\n />\n )\n }}\n isOptionEqualToValue={(option, value) => option._id === value._id}\n clearOnEscape\n filterOptions={(options, state) =>\n options.filter((option) => option.name.toLowerCase().includes(state.inputValue.toLowerCase()))\n }\n />\n \n )\n}\n\nconst useStyles = makeStyles(() =>\n createStyles({\n root: {\n margin: theme.spacing(1, 2),\n width: '200px',\n borderRadius: '16px',\n backgroundColor: theme.palette.white,\n },\n option: {\n padding: `${theme.spacing(1)} ${theme.spacing(2)}`,\n '&:hover': {\n backgroundColor: theme.palette.blueDianne[50],\n },\n },\n })\n)\n\nexport default TreeChartSearch\n","import { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport {\n faArrowsMaximize,\n faArrowsToCircle,\n faSitemap,\n faSlash,\n faMagnifyingGlassPlus,\n faMagnifyingGlassMinus,\n} from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Box, Button, Tooltip, styled } from '@mui/material'\nimport { makeStyles } from '@mui/styles'\nimport { FC } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { OrganizationListItem } from '@/types/organizations'\nimport TreeChartSearch from './TreeChartSearch'\nimport { theme } from '@/theme/theme'\n\ntype TreeChartActionsProps = {\n setShowSearchInput: (value: boolean) => void\n zoomIn: () => void\n zoomOut: () => void\n zoomToFit: () => void\n toggleAll: () => void\n collapsedAll: boolean\n recenterAccount: () => void\n showSearchInput: boolean\n searchValue: OrganizationListItem | null\n setSearchValue: (value: OrganizationListItem | null) => void\n handleSearch: (value: OrganizationListItem | null, collapse?: boolean, highlighted?: boolean) => void\n}\n\nconst ActionButton = styled(Button)({\n fontSize: '24px',\n '&:hover': {\n backgroundColor: theme.palette.blueDianne[50],\n },\n '&:active': {\n backgroundColor: theme.palette.cyan[500],\n },\n borderRadius: 0,\n})\n\nconst useStyles = makeStyles({\n root: {\n display: 'flex',\n alignItems: 'center',\n padding: theme.spacing(2, 1, 0),\n borderRadius: '0 8px 8px 0',\n backgroundColor: 'white',\n },\n})\n\nconst TreeChartActions: FC = ({\n setShowSearchInput,\n zoomIn,\n zoomOut,\n zoomToFit,\n toggleAll,\n collapsedAll,\n recenterAccount,\n searchValue,\n setSearchValue,\n handleSearch,\n}) => {\n const { t } = useTranslation()\n const classes = useStyles()\n\n return (\n <>\n \n setShowSearchInput(false)}\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 {!collapsedAll && }\n \n \n \n \n \n )\n}\n\nexport default TreeChartActions\n","export default \"__VITE_ASSET__fe382cb5__\"","export default \"__VITE_ASSET__543aced3__\"","import { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faBoxArchive, faPenToSquare, faSitemap, faSlash, faUpload } from '@fortawesome/pro-light-svg-icons'\nimport { faQuestion } from '@fortawesome/pro-solid-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Box, Typography } from '@mui/material'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport dayjs from 'dayjs'\nimport { FC } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport '/node_modules/flag-icons/css/flag-icons.min.css'\n\nimport { CurrentUser } from '@/api/profile/current-user'\nimport addIconHover from '@/assets/images/account-center-icons/add-hover.svg'\nimport addIcon from '@/assets/images/account-center-icons/add.svg'\nimport { OrganizationCardData } from '@/pages/AccountCenter'\nimport { theme } from '@/theme/theme'\nimport { OrganizationAccountType } from '@/types/organizations'\n\ntype TreeChartCardPros = {\n organization: OrganizationCardData\n depth: number\n opendChildren: any\n closedChildren: any\n currentUser: CurrentUser\n}\n\nconst cardBackgroundColors = [\n theme.palette.deepPurple[100],\n theme.palette.cyan[300],\n theme.palette.cyan[400],\n theme.palette.cyan[500],\n theme.palette.cyan[600],\n theme.palette.cyan[700],\n theme.palette.cyan[800],\n theme.palette.blueGray[200],\n theme.palette.indigo[200],\n theme.palette.indigo[100],\n]\n\nconst TreeChartCard: FC = ({ organization, depth, opendChildren, closedChildren, currentUser }) => {\n const classes = useStyles()\n const { t } = useTranslation()\n\n const isCreatorAdmin = organization.admin === currentUser.username\n const isParentOrganization = !!organization.number_of_children\n const isArchiveAuthorized = isCreatorAdmin && !isParentOrganization\n if (organization.id === 'fake_root') return <>\n\n return (\n \n \n {organization.name}\n \n {organization.logo ? (\n {organization.name}\n ) : (\n \n \n {t('accountCenter.card.uploadLogo')}\n \n )}\n \n \n \n \n \n {organization.origin_country ? (\n \n ) : (\n \n )}\n \n \n \n {t('accountCenter.card.activeMembersTitle')}\n
      \n {organization.active_members}\n
      \n {(opendChildren || closedChildren) && (\n \n {t('accountCenter.card.aggregatedActiveMembersTitle')}\n
      \n {organization.total_active_members}\n
      \n )}\n
      \n
      \n \n \n {opendChildren && {t('accountCenter.card.collapse')}}\n {closedChildren && {t('accountCenter.card.expand')}}\n {(closedChildren || opendChildren) && (\n <>\n \n {opendChildren && }\n \n )}\n \n \n {{t('accountCenter.card.edit')}}\n \n \n\n \n {\n \n {organization.is_admin_authorized && isArchiveAuthorized\n ? t('accountCenter.card.archive')\n : isCreatorAdmin\n ? t('accountCenter.card.organizationParentArchiveHover')\n : t('accountCenter.card.organizationCreatorArchiveHover')}\n \n }\n \n \n \n\n {organization.is_admin_authorized && organization.type !== OrganizationAccountType.client && (\n \n )}\n\n {dayjs(organization.created_at).isAfter(dayjs().subtract(30, 'days')) && (\n \n \n \n {t('accountCenter.card.newTooltipTitle', { days: dayjs().diff(dayjs(organization.created_at), 'day') })}\n \n {t('accountCenter.card.newTooltipMessege')}\n \n \n \n )}\n
      \n )\n}\n\nconst Bulge = () => (\n \n \n \n)\n\nconst NewBadge = () => (\n \n \n \n \n \n)\nconst useStyles = makeStyles(() =>\n createStyles({\n fakeRoot: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '420px',\n height: '140px',\n fontSize: '42px',\n borderRadius: '10px',\n border: '1px solid #B8B8B8',\n background: '#3AE2F9',\n },\n newBadgeWrapper: {\n position: 'absolute',\n top: '56px',\n right: '34px',\n },\n root: {\n margin: '12px 44px 0px 44px',\n borderRadius: '10px',\n display: 'flex',\n alignItems: 'center',\n flexDirection: 'column',\n border: '1px solid #B8B8B8',\n overflow: 'hidden',\n width: '192px',\n paddingTop: '10px',\n fontFamily: 'Montserrat',\n textAlign: 'center',\n '&.highlighted': {\n border: '4px solid #F8A33E',\n },\n },\n withTooltip: {\n '& p': {\n fontSize: '10px',\n fontWeight: theme.typography.fontWeightBold,\n position: 'absolute',\n transform: 'translate(26px,-9.5px)',\n padding: '6px 10px 6px',\n borderRadius: '20px',\n background: theme.palette.black + '90',\n color: 'white',\n opacity: 0,\n },\n '&:hover': {\n '& p': {\n opacity: 1,\n },\n },\n },\n longTooltip: {\n '& p': {\n transform: 'translate(0px,16px)',\n },\n },\n newTooltip: {\n '& p': {\n width: '254px',\n fontSize: '14px',\n fontWeight: theme.typography.fontWeightRegular,\n position: 'absolute',\n transform: 'translate(-95px,20px)',\n padding: '6px 12px 8px',\n borderRadius: '10px',\n background: theme.palette.black + '90',\n color: 'white',\n pointerEvents: 'none',\n '& b': {\n fontWeight: theme.typography.fontWeightBold,\n lineHeight: 2,\n },\n opacity: 0,\n },\n '&:hover': {\n '& p': {\n opacity: 1,\n },\n },\n },\n buttons: {\n position: 'absolute',\n right: 0,\n top: '25%',\n display: 'flex',\n flexDirection: 'column',\n },\n icon: {\n width: '24px',\n height: '24px',\n margin: '10px 0px',\n cursor: 'pointer',\n },\n disabledIcon: {\n cursor: 'not-allowed',\n '& svg': {\n opacity: 0.2,\n },\n },\n addIcon: {\n backgroundImage: `url(${addIcon})`,\n backgroundRepeat: 'no-repeat',\n backgroundPosition: 'center',\n width: '280px',\n height: '54px',\n '&.highlighted': {\n height: '55px',\n },\n '&:hover': {\n backgroundImage: `url(${addIconHover})`,\n },\n },\n organizationName: {\n fontWeight: '600',\n fontSize: 'min(16px,2vw)',\n width: '175px',\n height: '20px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n margin: '10px',\n },\n logoContainer: {\n background: 'white',\n width: '145px',\n height: '86px',\n display: 'flex',\n border: '1px solid #B8B8B8',\n borderRadius: '16px',\n },\n companyLogo: {\n width: '145px',\n padding: '10px',\n objectFit: 'contain',\n },\n uploadIcon: {\n width: '20px',\n height: '20px',\n margin: '-10px 0px 0px',\n },\n uploadText: {\n fontSize: '10px',\n margin: '-30px 2px',\n },\n bottom: {\n marginTop: '22px',\n padding: '7px 0px',\n height: '95px',\n width: '100%',\n background: 'black',\n },\n flagContainer: {\n marginTop: '-20px',\n position: 'absolute',\n },\n flag: {\n height: '22px',\n width: '30px',\n backgroundSize: 'cover',\n position: 'relative',\n marginLeft: '0.5px',\n marginBottom: '0.1px',\n },\n circleBox: {\n background: 'white',\n width: '20px',\n height: '20px',\n borderRadius: '50%',\n position: 'relative',\n margin: '-22px 10px 0px 11px',\n overflow: 'hidden',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'black',\n },\n detail: {\n color: 'white',\n fontWeight: '500',\n fontSize: '10px',\n '& span': {\n fontWeight: '800',\n fontSize: '12px',\n },\n },\n })\n)\n\nexport default TreeChartCard\n","import { Box } from '@mui/material'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport * as d3 from 'd3'\nimport { HierarchyNode } from 'd3-hierarchy'\nimport { OrgChart } from 'd3-org-chart'\nimport { Dispatch, FC, SetStateAction, useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport ReactDOMServer from 'react-dom/server'\n\nimport { useCurrentUser } from '@/api/profile/current-user'\nimport { ModalType, OrganizationCardData } from '@/pages/AccountCenter'\nimport { OrganizationListItem } from '@/types/organizations'\nimport TreeChartActions from './TreeChartActions'\nimport TreeChartCard from './TreeChartCard'\n\ntype TreeChartProps = {\n data: OrganizationCardData[]\n setModalType: Dispatch>\n setRelatedOrganization: Dispatch>\n setIsModalOpen: Dispatch>\n}\n\nconst TreeChart: FC = ({ data, setModalType, setRelatedOrganization, setIsModalOpen }) => {\n const [showSearchInput, setShowSearchInput] = useState(false)\n const [searchValue, setSearchValue] = useState(null)\n const [collapsedAll, setCollapsedAll] = useState(false)\n const d3Container = useRef(null)\n const chartRef = useRef | null>(null)\n\n //TODO Add autofocus\n const classes = useStyles()\n\n const { data: currentUser } = useCurrentUser()\n\n const clientOrg = useMemo(() => {\n return data.find((org) => org._id === currentUser?.current_client_id) || data[0]\n }, [data, currentUser])\n\n const addButtonOpenModalFunctionality = (\n node: HierarchyNode,\n modalType: ModalType,\n classNameSuffix: string\n ) => {\n const button = document.getElementById(node.id + classNameSuffix)\n if (button)\n button.onclick = () => {\n setModalType(modalType)\n setRelatedOrganization(node.data)\n setIsModalOpen(true)\n }\n }\n useLayoutEffect(() => {\n if (data.length === 0) return\n\n if (!chartRef.current) {\n chartRef.current = new OrgChart()\n }\n\n const chart = chartRef.current\n if (data && d3Container.current && currentUser) {\n chart\n .container(d3Container.current)\n .data(data)\n .nodeWidth(() => 280)\n .nodeHeight(() => 260)\n .childrenMargin(() => 75)\n .compactMarginBetween(() => 75)\n .compactMarginPair(() => 80)\n .nodeButtonHeight(() => 0)\n .buttonContent(() => '')\n .compact(false)\n .scaleExtent([0.1, 1])\n .initialZoom(1)\n .nodeContent((node) => {\n //@ts-ignore\n const closedChildren = node._children\n const opendChildren = node.children\n return ReactDOMServer.renderToStaticMarkup(\n \n )\n })\n .nodeUpdate((node) => {\n //@ts-ignore\n const closedChildren = node?._children\n const opendChildren = node.children\n node.data.id === 'fake_root' && chart.setExpanded('fake_root', true)\n const expandCollapseBtn = document.getElementById(node.id + '_expandCollapse')\n if (expandCollapseBtn)\n expandCollapseBtn.onclick = () => {\n if (closedChildren?.length) {\n chart.setExpanded(closedChildren[0].id as string).render()\n } else if (opendChildren?.length) {\n if (node.parent !== null) chart.setExpanded(opendChildren[0].id as string, false).render()\n else chart.collapseAll()\n }\n }\n addButtonOpenModalFunctionality(node, ModalType.edit, '_edit')\n addButtonOpenModalFunctionality(node, ModalType.clientSwitch, '_card')\n addButtonOpenModalFunctionality(node, ModalType.delete, '_archive')\n addButtonOpenModalFunctionality(node, ModalType.add, '_add')\n // addButtonOpenModalFunctionality(node, ModalType.upload, '_uploadImage')\n })\n .render()\n\n // no links from fake_root:\n d3.select(d3Container.current)\n .selectAll>('.link')\n .filter(function (d) {\n return d.depth === 1\n })\n .style('stroke', 'none')\n chart.setCentered(currentUser?.current_client_id ?? 'fake_root').expandAll()\n }\n }, [data, currentUser])\n\n const focusNode = (value: OrganizationListItem | null, collapse = true, highlighted = true) => {\n if (!value) {\n chartRef.current?.clearHighlighting()\n return\n }\n\n if (collapse) {\n chartRef.current?.clearHighlighting()\n\n const chartData = chartRef.current?.data()\n chartData?.forEach((node) => {\n node._expanded = false\n })\n chartData?.forEach((node) => {\n if (node.id === value._id) {\n node._highlighted = highlighted\n node._expanded = true\n }\n })\n }\n\n chartRef.current?.setCentered(value._id).initialZoom(1).render()\n }\n\n const toggleCollapse = () => {\n if (collapsedAll) {\n chartRef.current?.expandAll()\n } else {\n chartRef.current?.data()?.forEach((node) => {\n node.parentId === 'fake_root' ? (node._expanded = true) : (node._expanded = false)\n })\n chartRef.current?.data(data).render()\n }\n setCollapsedAll((currentCollapsed) => !currentCollapsed)\n }\n\n return (\n \n \n chartRef.current?.zoomIn()}\n zoomOut={() => chartRef.current?.zoomOut()}\n zoomToFit={() => chartRef.current?.setCentered(currentUser?.current_client_id ?? 'fake_root').render()}\n recenterAccount={() => focusNode(clientOrg, false, false)}\n toggleAll={toggleCollapse}\n collapsedAll={collapsedAll}\n showSearchInput={showSearchInput}\n searchValue={searchValue}\n setSearchValue={setSearchValue}\n handleSearch={focusNode}\n />\n \n \n )\n}\n\nconst useStyles = makeStyles(() =>\n createStyles({\n root: {\n flex: 1,\n '& .link': {\n strokeWidth: 2,\n stroke: '#B8B8B8',\n },\n '& svg': {\n height: '100%',\n },\n },\n treeChartActionsContainer: {\n position: 'absolute',\n top: 0,\n },\n })\n)\n\nexport default TreeChart\n","import { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faCalculatorSimple, faHouse } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Box, Button, Divider, Typography, styled } from '@mui/material'\nimport { Dispatch, FC, SetStateAction, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useNavigate } from 'react-router-dom'\n\nimport { useClientDetails } from '@/api/client/client'\nimport { useOrganizations } from '@/api/organizations/get'\nimport CywarenessBackground from '@/assets/images/logo-light-blue.svg'\nimport AddModal from '@/common/components/AccountCenter/AddModal'\nimport ArchivePopup from '@/common/components/AccountCenter/ArchivePopup'\nimport ClientSwitchPopup from '@/common/components/AccountCenter/ClientSwitchPopup'\nimport EditModal from '@/common/components/AccountCenter/EditModal'\nimport TreeChart from '@/common/components/AccountCenter/TreeChart'\nimport { theme } from '@/theme/theme'\nimport { OrganizationAccountType, OrganizationListItem } from '@/types/organizations'\n\nexport type OrganizationCardData = OrganizationListItem & {\n id: string\n parentId: string\n allow_support_admin_access?: boolean\n _highlighted: boolean\n _expanded: boolean\n}\n\nexport type ModalProps = {\n open: boolean\n modalType: ModalType\n setOpen: Dispatch>\n organization: OrganizationCardData\n focusNode?: (value: OrganizationListItem | null, collapse?: boolean, highlighted?: boolean) => void\n}\n\nexport enum ModalType {\n default,\n delete,\n edit,\n add,\n invite,\n clientSwitch,\n}\n\nconst AccountCenter: FC = () => {\n const { data } = useOrganizations()\n const { t } = useTranslation()\n const navigateTo = useNavigate()\n const { data: client } = useClientDetails()\n\n const [relatedOrganization, setRelatedOrganization] = useState({} as OrganizationCardData)\n const [modalType, setModalType] = useState(ModalType.default)\n const [isModalOpen, setIsModalOpen] = useState(false)\n\n const treeChartData: OrganizationCardData[] = useMemo(() => {\n if (!data?.length) return []\n const fakeRoot = {\n id: 'fake_root',\n name: 'Account Center',\n parentId: null,\n }\n\n const organizations = data.map((organization) => ({\n ...organization,\n id: organization._id,\n parentId: organization.parent_id === null ? 'fake_root' : organization.parent_id,\n }))\n\n return [fakeRoot, ...organizations]\n }, [data]) as OrganizationCardData[]\n\n return (\n \n \n \n \n {(client?.type === OrganizationAccountType.direct_reseller ||\n client?.type === OrganizationAccountType.distributor) && (\n {\n navigateTo('/account-center/pricing-calculator')\n }}\n endIcon={}>\n {t('accountCenter.pricingCalculator')}\n \n )}\n {\n navigateTo('/')\n }}\n endIcon={}>\n {t('accountCenter.backToDashboard')}\n \n \n \n \n {t('accountCenter.accountCenter')}\n \n \n \n \n )\n}\n\nconst AccountCenterModal: FC = ({ organization, open, setOpen, focusNode, modalType }) => {\n switch (modalType) {\n case ModalType.edit:\n return \n case ModalType.delete:\n return \n case ModalType.add:\n return \n case ModalType.clientSwitch:\n return \n }\n}\nconst StyledRootBox = styled(Box)(() => ({\n height: '100vh',\n position: 'relative',\n overflow: 'hidden',\n display: 'flex',\n flexDirection: 'column',\n backgroundImage: `url(${CywarenessBackground})`,\n backgroundPosition: 'bottom right',\n backgroundRepeat: 'no-repeat',\n}))\n\nconst StyledHeader = styled(Box)(() => ({\n width: '100%',\n height: '128px',\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(1),\n padding: theme.spacing(2),\n}))\n\nexport default AccountCenter\n","import useLottie from '@/common/hooks/useLottie'\nimport { useAuth } from '@/context/Auth'\nimport { theme } from '@/theme/theme'\nimport { Box, Button, Link, styled, Typography } from '@mui/material'\nimport archivedAnimationDataq from '@/assets/lottie/archived.json'\nimport { Trans, useTranslation } from 'react-i18next'\nimport { useClientDetails } from '@/api/client/client'\nimport { useLogout } from '@/api/auth/logout'\nimport { useNavigate } from 'react-router-dom'\nconst ArchivedOrganiztionPage = () => {\n const { user } = useAuth()\n const { data: client } = useClientDetails()\n const [logout] = useLogout()\n const navigateTo = useNavigate()\n const { t } = useTranslation()\n\n const { LottieAnimation } = useLottie({\n animationData: archivedAnimationDataq,\n width: 300,\n height: 300,\n options: {\n loop: true,\n autoplay: true,\n animationData: archivedAnimationDataq,\n rendererSettings: {\n preserveAspectRatio: 'xMidYMid slice',\n },\n },\n })\n\n const backToAccountCenter = () => {\n navigateTo('/account-center')\n }\n async function handleLogout() {\n await logout()\n navigateTo('/sign-in')\n }\n return (\n \n {t('archivedOrganization.title')}\n {t('archivedOrganization.subTitle')}\n {LottieAnimation}\n ,\n 2: ,\n }}\n values={{\n parentName: client?.parent_name,\n }}>\n {user?.has_multiple_clients ? (\n \n ) : (\n \n )}\n \n )\n}\n\nconst StyledContainer = styled(Box)({\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n flexDirection: 'column',\n textAlign: 'center',\n gap: theme.spacing(2),\n padding: theme.spacing(3),\n minHeight: '100vh',\n})\n\nconst StyledPattayaTypography = styled(Typography)(({ fontSize }: { fontSize: string }) => ({\n fontFamily: 'Pattaya',\n fontWeight: theme.typography.fontWeightRegular,\n background: `linear-gradient(${theme.palette.blueGray[200]}, ${theme.palette.blueDianne[900]} ,${theme.palette.grey[900]})`,\n WebkitBackgroundClip: 'text',\n WebkitTextFillColor: 'transparent',\n textAlign: 'center',\n fontSize: fontSize,\n padding: '0px 10px',\n marginBottom: '-20px',\n}))\n\nexport default ArchivedOrganiztionPage\n","export default \"__VITE_ASSET__53b4dfd3__\"","import { Box, keyframes, styled, Typography } from '@mui/material'\nimport { FC, ReactNode } from 'react'\nimport { useTranslation } from 'react-i18next'\n\nimport cywarenessLogo from '@/assets/images/logo-be-awere-stay-safe.svg'\nimport Fingerprint from '@/assets/images/logo-clean-blue.svg'\nimport SmartCityGif from '@/assets/images/smart-city.gif'\nimport { theme } from '@/theme/theme'\n\nconst FutureFormWrapper: FC<{ children: ReactNode }> = ({ children }) => {\n const { t } = useTranslation()\n return (\n \n \n \n {t('settings.admins.invitation.welcome')}\n \n {t('settings.admins.invitation.toTheFuture')}
      {t('settings.admins.invitation.cyberAwereness')}\n
      \n \n
      \n \n {children}\n \n
      \n )\n}\n\nconst FormWrapper: FC<{ logo: string; children: ReactNode }> = ({ logo, children }) => {\n const { t } = useTranslation()\n return (\n \n \n \n \n {children}\n \n \n {t('login.copyright', { year: new Date().getFullYear() })}\n \n \n \n )\n}\n\nconst upAnimation = keyframes`\n0% {\n transform: translate(0px, 600px);\n}\n50% {\n transform: translate(0px, 600px);\n}\n90% {\n transform: translate(0px, -10px);\n}\n100% {\n transform: translate(0px, 0px);\n}\n`\nconst downAnimation = keyframes`\n 0% {\n transform: translate(0px, -600px);\n }\n 50% {\n transform: translate(0px, -600px);\n }\n 90% {\n transform: translate(0px, 10px);\n }\n 100% {\n transform: translate(0px, 0px);\n }\n`\n\nconst StyledCard = styled(Box)(() => ({\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n height: 'fit-content',\n zIndex: 1,\n borderRadius: '20px',\n backgroundColor: 'white',\n padding: theme.spacing(3),\n margin: theme.spacing(3),\n}))\n\nconst StyledRightSide = styled(Box)(() => ({\n display: 'flex',\n flexGrow: 3,\n alignItems: 'center',\n justifyContent: 'center',\n}))\n\nconst StyledLeftSide = styled(Box)(() => ({\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n flexGrow: 2,\n justifyContent: 'center',\n padding: theme.spacing(2, 0),\n overflow: 'hidden',\n minWidth: '534px',\n height: '100vh',\n}))\n\nconst StyledGifBox = styled(Box)(() => ({\n backgroundImage: `url(${SmartCityGif})`,\n backgroundRepeat: 'no-repeat',\n backgroundSize: '60%',\n backgroundPosition: 'center',\n width: '100%',\n height: '100%',\n maxHeight: '380px',\n margin: '10% 0px 0px',\n animation: `${upAnimation} 7s ease`,\n}))\n\nconst StyledConentContainer = styled(Box)(() => ({\n display: 'flex',\n flexDirection: 'row',\n margin: '0px',\n width: '100%',\n height: '100%',\n justifyContent: 'flex-end',\n backgroundImage: `linear-gradient(35deg, ${theme.palette.white}, ${theme.palette.teal[50]} )`,\n}))\n\nconst StyledBackgroundLogo = styled(Box)(() => ({\n backgroundImage: `url(${Fingerprint})`,\n backgroundRepeat: 'no-repeat',\n backgroundSize: 'contain',\n position: 'fixed',\n opacity: '25%',\n bottom: '-20%',\n right: '-10%',\n width: '80%',\n minWidth: '500px',\n minHeight: '500px',\n height: '80%',\n scale: '-1 1',\n}))\n\nconst StyledPattayaTypography = styled(Typography)(({ fontSize }: { fontSize: string }) => ({\n fontFamily: 'Pattaya',\n fontWeight: theme.typography.fontWeightRegular,\n background: `linear-gradient(${theme.palette.blueGray[200]}, ${theme.palette.blueDianne[900]} ,${theme.palette.grey[900]})`,\n WebkitBackgroundClip: 'text',\n WebkitTextFillColor: 'transparent',\n textAlign: 'center',\n fontSize: fontSize,\n padding: '0px 10px',\n marginBottom: '-20px',\n animation: `${downAnimation} 7s ease`,\n}))\n\nexport default FutureFormWrapper\n","import { useMutation } from '@tanstack/react-query'\nimport axios from 'axios'\n\nimport { API_URL } from '../constants'\n\ntype MFASetup = {\n type: 'email' | 'app'\n}\n\nconst mfaSetup = async (setupPaypload: MFASetup) => {\n const url = `${API_URL}/profile/mfa/setup`\n const { data } = await axios.post(url, setupPaypload, {\n withCredentials: true,\n })\n\n return data\n}\n\nexport const useMFASetup = () => {\n return useMutation({ mutationFn: mfaSetup })\n}\n","import { useMutation } from '@tanstack/react-query'\nimport axios from 'axios'\n\nimport { API_URL } from '../constants'\nimport { useQueryCache } from 'react-query'\n\ntype MFAVerify = {\n token: string\n}\n\nconst mfaVerifySetup = async (mfaPaypload: MFAVerify) => {\n const url = `${API_URL}/profile/mfa/verify`\n const { data } = await axios.post(url, mfaPaypload, {\n withCredentials: true,\n })\n\n return data\n}\n\nconst mfaVerifyLogin = async (mfaPaypload: MFAVerify) => {\n const url = `${API_URL}/auth/verify-mfa/`\n const { data } = await axios.post(url, mfaPaypload, {\n withCredentials: true,\n })\n\n return data\n}\n\nexport const useMFAVerifySetup = () => {\n const queryCache = useQueryCache()\n\n return useMutation({\n mutationFn: mfaVerifySetup,\n onSuccess: () => {\n // Invalidate the user to refetch the data after MFa verification\n queryCache.invalidateQueries('user')\n },\n })\n}\n\nexport const useMFAVerifyLogin = () => {\n const queryCache = useQueryCache()\n\n return useMutation({\n mutationFn: mfaVerifyLogin,\n onSuccess: () => {\n // Invalidate the user to refetch the data after MFa verification\n queryCache.invalidateQueries('user')\n },\n })\n}\n","export const detectAutofill = (element: HTMLInputElement): Promise => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(window.getComputedStyle(element, null).getPropertyValue('appearance') === 'menulist-button')\n }, 50)\n })\n}\n\nexport const makeAnimationStartHandler =\n (stateSetter: React.Dispatch>, value: any) =>\n (e: React.AnimationEvent) => {\n const autofilledBrowser = Boolean((e.target as any)?.matches('*:-webkit-autofill'))\n const autofilled = autofilledBrowser || (value && value !== '')\n if (e.animationName === 'mui-auto-fill' || e.animationName === 'mui-auto-fill-cancel') {\n stateSetter(autofilled as boolean)\n }\n }\n","import { faExclamationSquare } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Typography } from '@mui/material'\nimport { FC, ReactNode } from 'react'\n\nimport { theme } from '@/theme/theme'\n\nconst HelperTextComponent: FC<{ hasError?: boolean; helperText?: ReactNode; sx?: any }> = ({\n hasError,\n helperText,\n sx,\n}) => {\n return hasError ? (\n \n \n {helperText}\n \n ) : (\n <>\n )\n}\n\nexport default HelperTextComponent\n","import { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faLockKeyhole } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { InputAdornment } from '@mui/material'\nimport MuiTextField, { TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField'\nimport { FieldHookConfig, useField } from 'formik'\nimport { ChangeEvent, FC, FocusEvent, useState } from 'react'\n\nimport { makeAnimationStartHandler } from '@/common/utils/detectAutofill-utils'\nimport { palette } from '@/theme/palette'\nimport HelperTextComponent from '../HelperTextComponent'\n\nexport enum FieldClasses {\n validate = 'validate',\n locked = 'locked',\n}\n//NOTE: Rename this to v2.tsx file to index after refactorin all the places where current TextField is used\nexport const MuiTextFieldSX = {\n // marding for the helper text\n // TODO: consider moving the class name to theme variant/ styledComponent prop\n '&.validate': {\n marginRight: '12px',\n },\n width: '100%',\n maxHeight: '68px',\n '& .MuiOutlinedInput-root': {\n height: '56px',\n background: palette.white,\n borderRadius: '10px',\n '& legend': {\n width: 0,\n },\n '&.Mui-focused fieldset': {\n border: '1px solid',\n },\n '& .MuiInputAdornment-root': {\n fontSize: '14px',\n marginRight: '-4px',\n paddingRight: '0px',\n },\n\n '&.MuiInputBase-colorSecondary': {\n background: palette.blueGray[800],\n color: palette.white,\n fieldset: {\n border: `1px solid ${palette.cyan[500]}`,\n },\n '& .MuiInputAdornment-root': {\n color: palette.white,\n },\n },\n },\n '& .MuiFormHelperText-root': {\n marginLeft: '0px',\n marginTop: '0px',\n },\n '& .MuiInputLabel-root[data-shrink=\"false\"]': {\n fontSize: '16px',\n color: palette.grey[500],\n '& .MuiFormLabel-asterisk': {\n color: 'inherit', // Inherits the label color instead of turning red\n },\n },\n '& .MuiInputLabel-root.MuiFormLabel-colorSecondary[data-shrink=\"false\"]': {\n color: palette.grey[300],\n },\n\n '& .MuiInputLabel-root.Mui-disabled': {\n color: palette.grey[600],\n background: palette.grey[400],\n },\n\n '& .MuiInputLabel-root[data-shrink=\"true\"]': {\n marginTop: '1px',\n padding: '2px 8px 2px 8px',\n fontSize: '12px',\n background: palette.white,\n borderRadius: '5px',\n color: palette.blueDianne[900],\n },\n '& .MuiInputLabel-root.MuiFormLabel-colorSecondary[data-shrink=\"true\"]': {\n background: palette.blueGray[800],\n color: palette.white,\n },\n\n '& .MuiOutlinedInput-root.Mui-disabled': {\n background: palette.grey[300],\n },\n '& .MuiInputLabel-root.Mui-error': {\n color: palette.grey[500], // Keep the label color unchanged on error\n },\n '&.locked': {\n '& .MuiInputLabel-root.Mui-disabled': {\n color: palette.blueDianne[900] + '!important',\n background: palette.grey[200] + '!important',\n },\n '& .MuiOutlinedInput-root.Mui-disabled .MuiOutlinedInput-input': {\n color: palette.blueDianne[900] + '!important',\n '-webkit-text-fill-color': palette.blueDianne[900] + '!important',\n },\n '& .MuiOutlinedInput-root.Mui-disabled': {\n color: palette.blueDianne[900] + '!important',\n background: palette.grey[200] + '!important',\n },\n '& .MuiInputLabel-root[data-shrink=\"true\"]': {\n background: palette.white + '!important',\n },\n },\n}\n\ninterface TextFieldProps\n extends Omit,\n Pick, 'name'> {\n disableFormik?: boolean\n label: MuiTextFieldProps['label']\n value?: MuiTextFieldProps['value']\n isLocked?: boolean\n onChange?: MuiTextFieldProps['onChange']\n onBlur?: MuiTextFieldProps['onBlur']\n className?: string\n}\n\nconst TextField: FC = ({\n name,\n label,\n InputProps,\n InputLabelProps,\n disableFormik = false,\n className,\n onChange,\n onBlur,\n ...otherProps\n}) => {\n const [fieldHasValue, setFieldHasValue] = useState(false)\n const [field, meta] = useField(name)\n const combinedInputProps = className?.includes(FieldClasses.locked)\n ? {\n endAdornment: (\n \n \n \n ),\n }\n : {}\n\n const configTextField: MuiTextFieldProps = {\n ...otherProps,\n fullWidth: true,\n label,\n // placeholder: label as string,\n // InputLabelProps: combinedInputLabelProps,\n InputProps: {\n ...(combinedInputProps as any),\n onAnimationStart: makeAnimationStartHandler(setFieldHasValue, otherProps.value), //autofill fix!!\n ...InputProps,\n },\n InputLabelProps: { shrink: fieldHasValue, ...InputLabelProps },\n }\n\n if (!disableFormik) {\n // Merge Formik-related props if Formik is enabled\n Object.assign(configTextField, {\n ...field,\n className: [disableFormik ? '' : FieldClasses.validate, className].join(' '),\n error: meta.touched && Boolean(meta.error),\n helperText: ,\n onChange: onChange\n ? (event: ChangeEvent) => {\n field.onChange(event)\n onChange(event)\n }\n : field.onChange,\n onBlur: onBlur\n ? (event: FocusEvent) => {\n field.onBlur(event)\n onBlur(event)\n }\n : field.onBlur,\n })\n } else {\n // Attach provided onChange and onBlur handlers for non-Formik usage\n if (onChange) configTextField.onChange = onChange\n if (onBlur) configTextField.onBlur = onBlur\n }\n\n return \n}\n\nexport default TextField\n","import { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faChevronLeft } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport LoadingButton from '@mui/lab/LoadingButton'\nimport { Alert, Box, Collapse, Link, Skeleton, Typography } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { QRCodeSVG } from 'qrcode.react'\nimport { FC, useEffect, useState } from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\nimport { Link as ReactLink, useNavigate } from 'react-router-dom'\n//@ts-ignore\nimport * as Yup from 'yup'\n\nimport { useMFASetup } from '@/api/auth/mfa-setup'\nimport { useMFAVerifySetup } from '@/api/auth/mfa-verify'\nimport { useCurrentUser } from '@/api/profile/current-user'\nimport { getErrorMessage } from '@/api/utils/get-error'\nimport TextField from '@/common/components/Inputs/TextFieldV2'\nimport useToast from '@/common/hooks/useToast'\nimport { theme } from '@/theme/theme'\n\nconst App: FC = () => {\n const { t } = useTranslation()\n const { errorToast, successToast } = useToast()\n const navigateTo = useNavigate()\n\n const [isHelpVisible, setIsHelpVisible] = useState(false)\n const [appData, setAppData] = useState({ uri: '', secret: '' })\n\n const { data: currentUser } = useCurrentUser()\n\n const initialValues = {\n token: '',\n }\n\n const validationSchema = Yup.object().shape({\n token: Yup.string().required('Field required'),\n })\n\n const { mutateAsync: mfaSetup, isPending } = useMFASetup()\n const { mutateAsync: mfaVerify } = useMFAVerifySetup()\n\n const handleSubmit = async (\n values: { token: string },\n { setFieldError }: { setFieldError: (field: string, message: string | undefined) => void }\n ) => {\n try {\n await mfaVerify({ token: values.token })\n successToast(t('mfa.success'))\n navigateTo(currentUser?.mfa_enabled ? `/settings/admins/${currentUser.id}` : '/sing-in')\n } catch (error) {\n const message = getErrorMessage(error)\n setFieldError('token', message)\n }\n }\n\n useEffect(() => {\n const setup = async () => {\n try {\n const appData = await mfaSetup({ type: 'app' })\n setAppData(appData)\n } catch (error) {\n errorToast(error)\n }\n }\n\n setup()\n }, [mfaSetup, setAppData])\n\n return (\n \n {({ isSubmitting, isValid, dirty }) => (\n
      \n \n \n {t('mfa.title')}\n \n \n }} />\n \n \n , 2:
      }} />\n
      \n \n \n \n {isPending ? (\n \n ) : (\n \n )}\n \n \n \n \n }}\n />\n \n \n \n \n {\n setIsHelpVisible((prev) => !prev)\n }}>\n {t('mfa.setup.app.step2qrTruble')}\n \n \n \n }} />\n \n\n \n \n \n\n \n \n {t('mfa.form.submit')}\n \n \n \n \n \n {t('mfa.backToMethods')}\n \n \n
      \n
      \n )}\n
      \n )\n}\n\nexport default App\n","import { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faEnvelope, faMobile } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport LoadingButton from '@mui/lab/LoadingButton'\nimport { Box, styled, Typography } from '@mui/material'\nimport { FC } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useNavigate } from 'react-router-dom'\n\nimport { theme } from '@/theme/theme'\n\nconst ChooseType: FC = ({}) => {\n const { t } = useTranslation()\n const navigateTo = useNavigate()\n\n return (\n \n \n {t('mfa.title')}\n \n {t('mfa.setup.chooseMethod')}\n \n navigateTo('/mfa-setup/app')}>\n \n {t('mfa.setup.methodApp')}\n \n navigateTo('/mfa-setup/email')}>\n \n {t('mfa.setup.methodEmail')}\n \n \n \n )\n}\n\nconst AppLoadingButton = styled(LoadingButton)({\n width: 128,\n height: 128,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n borderWidth: 5,\n borderColor: theme.palette.cyan[50],\n gap: 16,\n borderRadius: 8,\n '&:hover': {\n borderWidth: 5,\n borderColor: theme.palette.cyan[100],\n },\n '&:active': {\n borderWidth: 5,\n borderColor: theme.palette.cyan[200],\n },\n '&:disabled': {\n borderWidth: 5,\n borderColor: theme.palette.grey[100],\n },\n})\n\nexport default ChooseType\n","import { Moment } from 'moment'\n\nexport function secondsToDays(seconds: number) {\n return Math.round(seconds / 86400)\n}\n\nexport function calculateBusinessDays(firstDate: Moment, secondDate: Moment) {\n let day1 = firstDate.clone().startOf('day')\n let day2 = secondDate.clone().startOf('day')\n\n const weekends = [6, 0] // 6 = Saturday, 0 = Sunday\n const days = day2.diff(day1, 'days') + 1\n const fullWeeks = Math.floor(days / 7)\n const remainingDays = days % 7\n let businessDays = fullWeeks * 5\n\n for (let i = 1; i <= remainingDays; i++) {\n const day = day1.clone().add(i, 'days').day()\n if (!weekends.includes(day)) {\n businessDays++\n }\n }\n\n return businessDays\n}\n\nexport const formatSeconds = (seconds: number) => {\n const minutes = Math.floor(seconds / 60)\n .toString()\n .padStart(2, '0')\n const secs = (seconds % 60).toString().padStart(2, '0')\n return `${minutes}:${secs}`\n}\n","import { Typography } from '@mui/material'\nimport { Trans, useTranslation } from 'react-i18next'\n//@ts-ignore\n\nimport { formatSeconds } from '@/common/utils/time'\nimport { theme } from '@/theme/theme'\nimport { FC, useEffect, useState } from 'react'\n\ntype EmailResendTimerProps = {\n handleClick: () => void\n time?: number\n}\n\nconst EmailResendTimer: FC = ({ handleClick, time = 60 }) => {\n const { t } = useTranslation()\n const [resendTimer, setResendTimer] = useState(0)\n\n useEffect(() => {\n if (resendTimer === 0) return\n const timerId = setInterval(() => {\n setResendTimer((prev) => prev - 1)\n }, 1000)\n return () => clearInterval(timerId)\n }, [resendTimer])\n\n if (resendTimer)\n return (\n \n {t('mfa.resendTimer')} {formatSeconds(resendTimer)}\n \n )\n\n return (\n \n {\n handleClick()\n setResendTimer(60)\n }}\n component=\"text\"\n color={theme.palette.blue[900]}\n fontWeight={theme.typography.fontWeightSemiBold}\n textDecoration=\"underline\"\n sx={{ cursor: 'pointer' }}\n />\n ),\n }}\n />\n \n )\n}\n\nexport default EmailResendTimer\n","import { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faChevronLeft } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport LoadingButton from '@mui/lab/LoadingButton'\nimport { Box, Link, Typography } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { FC, useEffect } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { Link as ReactLink, useNavigate } from 'react-router-dom'\n//@ts-ignore\nimport * as Yup from 'yup'\n\nimport { useCurrentUser } from '@/api/profile/current-user'\nimport EmailResendTimer from '@/common/components/EmailResend'\nimport TextField from '@/common/components/Inputs/TextFieldV2'\nimport { theme } from '@/theme/theme'\nimport useToast from '@/common/hooks/useToast'\nimport { useMFASetup } from '@/api/auth/mfa-setup'\nimport { getErrorMessage } from '@/api/utils/get-error'\nimport { useMFAVerifySetup } from '@/api/auth/mfa-verify'\n\nconst Email: FC = () => {\n const { t } = useTranslation()\n const { errorToast, successToast } = useToast()\n const navigateTo = useNavigate()\n\n const { data: currentUser } = useCurrentUser()\n\n // console.log('loginflow', currentUser)\n // if (currentUser?.mfa_enabled) {\n // //\n // }\n\n const initialValues = {\n token: '',\n }\n\n const validationSchema = Yup.object().shape({\n token: Yup.string().required('Field required'),\n })\n\n const { mutateAsync: mfaSetup } = useMFASetup()\n const { mutateAsync: mfaVerify } = useMFAVerifySetup()\n\n const handleResend = async () => {\n try {\n await mfaSetup({ type: 'email' })\n } catch (error) {\n errorToast(error)\n }\n }\n\n const handleSubmit = async (\n values: { token: string },\n { setFieldError }: { setFieldError: (field: string, message: string | undefined) => void }\n ) => {\n try {\n await mfaVerify({ token: values.token })\n successToast(t('mfa.success'))\n navigateTo(currentUser?.mfa_enabled ? `/settings/admins/${currentUser.id}` : '/sing-in')\n } catch (error) {\n const message = getErrorMessage(error)\n setFieldError('token', message)\n }\n }\n\n useEffect(() => {\n const setup = async () => {\n try {\n await mfaSetup({ type: 'email' })\n } catch (error) {\n errorToast(error)\n }\n }\n\n setup()\n }, [mfaSetup])\n\n return (\n \n {({ isSubmitting, isValid, dirty }) => (\n
      \n \n \n {t('mfa.title')}\n \n \n {t('mfa.enterCodeDescriptionEmail', { username: currentUser?.username })}\n \n\n \n \n \n\n \n\n \n \n {t('mfa.form.submit')}\n \n \n \n \n \n {t('mfa.backToMethods')}\n \n \n \n
      \n )}\n
      \n )\n}\n\nexport default Email\n","import { FC } from 'react'\nimport { Route, Routes } from 'react-router-dom'\n\nimport FutureFormWrapper from '@/common/components/Layout/FutureFormWrapper'\nimport App from './App'\nimport ChooseType from './ChooseType'\nimport Email from './Email'\n\nconst FMASetupPage: FC = () => {\n return (\n \n \n } />\n } />\n } />\n \n \n )\n}\n\nexport default FMASetupPage\n","import axios from 'axios'\nimport { API_URL } from '@/api/constants'\nimport { useMutation } from '@tanstack/react-query'\n\ntype RequestPasswordResetPayload = {\n username: string\n password: string\n recaptcha: string\n}\n\ntype RequestPasswordResetResponse = {}\n\nconst requestPasswordReset = async (\n requestPasswordResetPayload: RequestPasswordResetPayload\n): Promise => {\n const { data } = await axios.post(`${API_URL}/auth/request-password-reset/`, requestPasswordResetPayload, {\n withCredentials: true,\n })\n\n return data\n}\n\nexport const useRequestPasswordReset = () => {\n return useMutation({ mutationFn: requestPasswordReset })\n}\n","import LoadingButton from '@mui/lab/LoadingButton'\nimport { Box } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { FC } from 'react'\nimport { useGoogleReCaptcha } from 'react-google-recaptcha-v3'\nimport { useTranslation } from 'react-i18next'\nimport { useNavigate } from 'react-router-dom'\n//@ts-ignore\nimport * as Yup from 'yup'\n\nimport { useRequestPasswordReset } from '@/api/auth/request-password-reset'\nimport { theme } from '@/theme/theme'\nimport TextField from '@/common/components/Inputs/TextFieldV2'\n\nconst ResetPasswordEmail: FC = () => {\n const { t } = useTranslation()\n const navigateTo = useNavigate()\n const { executeRecaptcha } = useGoogleReCaptcha()\n const { mutateAsync: requestPasswordReset } = useRequestPasswordReset()\n\n const handleSubmit = async (values: { username: string; password: string }) => {\n const recaptcha = (executeRecaptcha && (await executeRecaptcha('forgot_password'))) || ''\n await requestPasswordReset({ ...values, recaptcha })\n navigateTo(`/reset-password/verify/${values.username}`)\n }\n const initialValues = {\n username: '',\n password: '',\n }\n const validationSchema = Yup.object().shape({\n username: Yup.string().email('Invalid email').required('Field required'),\n })\n\n return (\n \n {({ isSubmitting, isValid, dirty }) => (\n
      \n \n \n \n \n {t('resetPassword.sendEmail')}\n \n \n \n
      \n )}\n
      \n )\n}\n\nexport default ResetPasswordEmail\n","import axios from 'axios'\nimport { useMutation } from 'react-query'\nimport { API_URL } from '../constants'\nimport { ServerError } from '../types'\n\ntype VerifyTokenParams = {\n username: string | undefined\n token: string\n}\n\ntype VerifyTokenResponse = {}\n\nasync function verifyToken(params: VerifyTokenParams): Promise {\n const url = `${API_URL}/auth/verify-password-reset-token/`\n const { data } = await axios.post(url, { ...params })\n return data\n}\n\nexport function useVerifyPasswordResetToken(callback) {\n return useMutation(verifyToken, {\n onSuccess: callback,\n })\n}\n","import LoadingButton from '@mui/lab/LoadingButton'\nimport { Box, Typography } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { FC, useEffect, useState } from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\nimport { useNavigate, useParams } from 'react-router-dom'\n//@ts-ignore\nimport * as Yup from 'yup'\n\nimport { useVerifyPasswordResetToken } from '@/api/auth/verify-password-reset-token'\nimport { ServerError } from '@/api/types'\nimport TextField from '@/common/components/Inputs/TextFieldV2'\n\nconst VerifyResetToken: FC = () => {\n const { t } = useTranslation()\n const navigateTo = useNavigate()\n const { username } = useParams()\n const [token, setToken] = useState('')\n const [verified, setVerified] = useState(false)\n\n const [verifyToken, { isLoading }] = useVerifyPasswordResetToken(() => {\n setVerified(true)\n })\n\n useEffect(() => {\n if (verified) navigateTo(`/reset-password/set-new/${username}/${token}`)\n }, [verified])\n\n const handleSubmit = async (\n values: { token: string },\n { setFieldError }: { setFieldError: (field: string, message: string | undefined) => void }\n ) => {\n try {\n setToken(values.token)\n await verifyToken({ ...values, ...{ username } })\n } catch (e) {\n setFieldError('token', (e as ServerError).response.data.message)\n }\n }\n\n const initialValues = {\n token: '',\n }\n const validationSchema = Yup.object().shape({\n token: Yup.string().required('Field required'),\n })\n\n return (\n \n {({ isSubmitting, isValid, dirty }) => (\n
      \n \n \n ,\n }}\n values={{ username: username }}\n />\n \n \n \n \n {t('verifyToken.verify')}\n \n \n \n
      \n )}\n
      \n )\n}\n\nexport default VerifyResetToken\n","import axios from \"axios\";\nimport { API_URL } from \"../constants\";\nimport { useMutation } from \"react-query\";\nimport { ServerError } from \"../types\";\n\ntype ResetPasswordParams = {\n username: string | undefined;\n password: string;\n token: string | undefined;\n};\n\ntype ResetPasswordResponse = {};\n\nasync function resetPassword(\n params: ResetPasswordParams\n): Promise {\n const url = `${API_URL}/auth/reset-password/`;\n const { data } = await axios.post(url, { ...params });\n return data;\n}\n\nexport function useResetPassword(callback) {\n return useMutation(\n resetPassword,\n {\n onSuccess: callback,\n }\n );\n}\n","import { Box, Typography, styled } from '@mui/material'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { faCircleCheck } from '@fortawesome/pro-solid-svg-icons'\nimport { DIGITS_REGEX, LOWERCASE_REGEX, SPECIAL_CHARACTERS_REGEX, UPPERCASE_REGEX } from '@/api/constants'\nimport { FC } from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\nimport { theme } from '@/theme/theme'\n\n//TODO: move to the palette!\n\nexport type EvaluationSize = 'small' | 'medium' | 'large'\n\nconst ColorLineSizeMap: Record = {\n small: '56px',\n medium: '75px',\n large: '154px',\n}\nconst SmallTypographySizeMap: Record = {\n small: '10px',\n medium: '12px',\n large: '14px',\n}\nconst marginRightSizeMap: Record = {\n small: '10px',\n medium: '20px',\n large: '30px',\n}\nconst iconSizeMap: Record = {\n small: '14px',\n medium: '16px',\n large: '18px',\n}\nconst iconMarginSizeMap: Record = {\n small: theme.spacing(0.5),\n medium: theme.spacing(1),\n large: theme.spacing(1.5),\n}\nconst RED = theme.palette.pink[500]\nconst GREEN = theme.palette.green[600]\nconst ORANGE = theme.palette.orange[500]\nconst GRAY = theme.palette.grey[300]\nconst DARK_GRAY = theme.palette.grey[500]\n\nconst PasswordStrengthEvaluation: FC<{ password: string; size: EvaluationSize }> = ({ password, size = 'medium' }) => {\n const { t } = useTranslation()\n const isUpperLowerCase = UPPERCASE_REGEX.test(password) && LOWERCASE_REGEX.test(password) ? 1 : 0\n const number = DIGITS_REGEX.test(password) ? 1 : 0\n const specialCharcter = SPECIAL_CHARACTERS_REGEX.test(password) ? 1 : 0\n const minLength = password.length > 7 ? 1 : 0\n const strength = isUpperLowerCase + number + specialCharcter + minLength\n const grade = strength > 3 ? 'STRONG' : strength > 1 ? 'MEDIUM' : 'WEAK'\n return (\n <>\n \n 3 ? GREEN : strength > 1 ? ORANGE : RED} />\n 3 ? GREEN : strength > 1 ? ORANGE : GRAY} />\n 3 ? GREEN : strength > 1 ? GRAY : GRAY} />\n {grade}\n \n \n ,\n }}\n />\n \n \n \n \n \n {t('settings.admins.password.upperLowercase')}\n \n \n \n {t('settings.admins.password.number')}\n \n \n \n \n \n {t('settings.admins.password.specialCharacter')}\n \n \n \n {t('settings.admins.password.minCharacters')}\n \n \n \n \n )\n}\n\nconst RowBox = styled(Box)(() => ({\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n}))\nconst CheckWrapper = styled(RowBox)(() => ({\n marginBottom: '10px',\n}))\nconst ColorLine = styled(Box)(({ color, size }: { color: string; size: EvaluationSize }) => ({\n width: ColorLineSizeMap[size],\n height: '9px',\n background: color,\n borderRadius: '15px',\n margin: ' 0px 4px',\n}))\nconst SmallTypography = styled(Typography)(({ size }: { size: EvaluationSize }) => ({\n fontFamily: 'Montserrat',\n fontSize: SmallTypographySizeMap[size],\n}))\n\nexport default PasswordStrengthEvaluation\n","import PasswordStrengthEvaluation, { EvaluationSize } from '@/pages/Settings/Admins/PasswordStrengthEvaluation'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faEye, faEyeSlash } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Box, Collapse, InputAdornment } from '@mui/material'\nimport MuiTextField, { TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField'\nimport { FieldHookConfig, useField } from 'formik'\nimport { ChangeEvent, FC, FocusEvent, useState } from 'react'\n\nimport { makeAnimationStartHandler } from '@/common/utils/detectAutofill-utils'\nimport HelperTextComponent from '../HelperTextComponent'\nimport { MuiTextFieldSX } from '../TextFieldV2/'\n\ninterface PasswordFieldProps\n extends Omit,\n Pick, 'name'> {\n withStrengthIndicator?: boolean\n strengthIndicatorSize?: EvaluationSize\n disableFormik?: boolean\n label: MuiTextFieldProps['label']\n value?: MuiTextFieldProps['value']\n onChange?: MuiTextFieldProps['onChange']\n onBlur?: MuiTextFieldProps['onBlur']\n}\n\nconst PasswordField: FC = ({\n name,\n label,\n InputProps,\n InputLabelProps,\n withStrengthIndicator = false,\n strengthIndicatorSize = 'small',\n disableFormik = false,\n onChange,\n onBlur,\n ...otherProps\n}) => {\n const [isPasswordVisible, setIsPasswordVisible] = useState(false)\n const [field, meta] = useField(name)\n const [fieldHasValue, setFieldHasValue] = useState(false)\n\n const configTextField: MuiTextFieldProps = {\n ...otherProps,\n fullWidth: true,\n label: label,\n placeholder: '********',\n InputProps: {\n ...({\n endAdornment: (\n \n setIsPasswordVisible((e) => !e)}\n icon={(isPasswordVisible ? faEyeSlash : faEye) as IconProp}\n />\n \n ),\n } as any),\n onAnimationStart: makeAnimationStartHandler(setFieldHasValue, otherProps.value),\n ...InputProps,\n },\n InputLabelProps: { shrink: fieldHasValue, ...InputLabelProps },\n }\n\n if (!disableFormik) {\n // Merge Formik-related props if Formik is enabled\n Object.assign(configTextField, {\n ...field,\n className: disableFormik ? '' : 'validate',\n error: meta.touched && Boolean(meta.error),\n helperText: ,\n onChange: onChange\n ? (event: ChangeEvent) => {\n field.onChange(event)\n onChange(event)\n }\n : field.onChange,\n onBlur: onBlur\n ? (event: FocusEvent) => {\n field.onBlur(event)\n onBlur(event)\n }\n : field.onBlur,\n })\n } else {\n // Attach provided onChange and onBlur handlers for non-Formik usage\n if (onChange) configTextField.onChange = onChange\n if (onBlur) configTextField.onBlur = onBlur\n }\n\n return (\n \n \n \n \n \n \n )\n}\n\nexport default PasswordField\n","import LoadingButton from '@mui/lab/LoadingButton'\nimport { Box } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { FC } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useNavigate, useParams } from 'react-router-dom'\n//@ts-ignore\nimport * as Yup from 'yup'\n\nimport { useResetPassword } from '@/api/auth/reset-password'\nimport { DIGITS_REGEX, LOWERCASE_REGEX, SPECIAL_CHARACTERS_REGEX, UPPERCASE_REGEX } from '@/api/constants'\nimport PasswordField from '@/common/components/Inputs/PasswordField'\nimport TextField from '@/common/components/Inputs/TextFieldV2'\n\nconst SetPassword: FC = () => {\n const { t } = useTranslation()\n const [setNewPassword, { isLoading }] = useResetPassword(() => navigateTo('/reset-password/success'))\n const { username, token } = useParams()\n const navigateTo = useNavigate()\n\n const isStrongPassword = (password: string) => {\n return (\n UPPERCASE_REGEX.test(password) &&\n LOWERCASE_REGEX.test(password) &&\n DIGITS_REGEX.test(password) &&\n SPECIAL_CHARACTERS_REGEX.test(password) &&\n password.length > 7\n )\n }\n\n const handleSubmit = async (values: { newPassword: string }) => {\n setNewPassword({ password: values.newPassword, username, token })\n }\n const initialValues = {\n username: username,\n newPassword: '',\n confirmNewPassword: '',\n }\n const validationSchema = Yup.object().shape({\n confirmNewPassword: Yup.string().test(\n 'confirm-new-password-check',\n \"Passwords don't match\",\n function (this: Yup.TestContext, value: string | undefined) {\n const { newPassword } = this.parent\n if (!newPassword && !value) return true\n return value === newPassword || this.createError({ message: \"Passwords don't match\" })\n }\n ),\n })\n\n return (\n \n {({ isSubmitting, isValid, dirty, values }) => (\n
      \n \n \n \n \n \n \n {t('setPassword.resetPassword')}\n \n \n \n
      \n )}\n
      \n )\n}\n\nexport default SetPassword\n","export default \"__VITE_ASSET__e8e562d6__\"","import { Box, Button, Typography } from '@mui/material'\nimport { FC } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useNavigate } from 'react-router-dom'\n\nimport successImage from '@/assets/images/auth/success.svg'\n\nconst ResetPasswordSuccess: FC = () => {\n const { t } = useTranslation()\n const navigateTo = useNavigate()\n return (\n \n {t('resetPasswordSuccess.passwordChanged')} \n \n \"bouncer\"\n \n \n \n \n \n )\n}\nexport default ResetPasswordSuccess\n","import FutureFormWrapper from '@/common/components/Layout/FutureFormWrapper'\nimport { FC } from 'react'\nimport { Link, Route, Routes, useMatch } from 'react-router-dom'\nimport ResetPasswordEmail from './ResetPasswordEmail'\nimport VerifyResetToken from './VerifyResetToken'\nimport SetPassword from './SetPassword'\nimport ResetPasswordSuccess from './ResetPasswordSuccess'\nimport { Box, Typography } from '@mui/material'\nimport { theme } from '@/theme/theme'\nimport { Trans, useTranslation } from 'react-i18next'\n\nconst ResetPasswordPage: FC = () => {\n const { t } = useTranslation()\n const isSuccessPage = useMatch('/reset-password/success')\n\n return (\n \n \n \n {isSuccessPage ? 'Success!' : t('resetPassword.resetPassword')}\n \n \n } />\n } />\n } />\n } />\n \n {!isSuccessPage && (\n \n \n ),\n }}\n />\n \n )}\n \n \n )\n}\n\nexport default ResetPasswordPage\n","import axios from 'axios'\nimport { useMutation } from 'react-query'\n\nimport { ServerError } from '../types'\nimport { API_URL } from '../constants'\n\nexport type SignupParams = {\n full_name: string\n username: string\n password: string\n company_domains: string[]\n company_name: string\n phone_number: string\n recaptcha: string\n promo_code?: string\n accept_terms: boolean\n terms: string\n}\n\nexport type SignupResponse = {\n used_promo_code: boolean\n applied_configurations: {\n [key: string]: string\n }\n}\n\nasync function signup(signupData: SignupParams): Promise {\n const { data } = await axios.post(`${API_URL}/auth/signup/`, { ...signupData })\n return data\n}\n\nexport function useSignup() {\n return useMutation(signup, {\n throwOnError: true,\n })\n}\n","import axios from 'axios'\nimport { API_URL } from '../constants'\nimport { Terms } from '@/types/terms'\nimport { useQuery } from '@tanstack/react-query'\n\nconst getLatestTerms = async () => {\n const { data } = await axios.get(`${API_URL}/terms/latest`)\n return data\n}\n\nconst useGetLatestTerms = () => {\n return useQuery({\n queryKey: ['latest-terms'],\n queryFn: getLatestTerms,\n })\n}\n\nexport { getLatestTerms, useGetLatestTerms }\n","import { InputAdornment, MenuItem, Select, TextField, Typography } from '@mui/material'\nimport { MuiTextFieldProps } from '@mui/x-date-pickers/internals'\nimport { useField } from 'formik'\nimport { FC } from 'react'\nimport {\n CountryIso2,\n defaultCountries,\n FlagImage,\n parseCountry,\n ParsedCountry,\n usePhoneInput,\n} from 'react-international-phone'\nimport 'react-international-phone/style.css'\n\nimport { theme } from '@/theme/theme'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faLockKeyhole } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport HelperTextComponent from '../HelperTextComponent'\nimport { FieldClasses, MuiTextFieldSX } from '../TextFieldV2/'\n\ntype PhoneNumberFieldProps = {\n name: string\n label: string\n value?: string\n disableFormik?: boolean\n className?: string\n defaultCountry?: string\n onChange?: (newValue: string) => void\n disabled?: boolean\n}\n\ntype CountrySelectProps = {\n country: ParsedCountry\n setCountry: (country: CountryIso2) => void\n disabled?: boolean\n}\n\nconst PhoneNumberField: FC = ({\n name,\n label,\n value,\n disableFormik = false,\n defaultCountry = 'us',\n className,\n onChange,\n ...otherProps\n}) => {\n const [field, meta, helpers] = useField(name)\n\n const configTextField: MuiTextFieldProps = {\n ...otherProps,\n fullWidth: true,\n label: label,\n placeholder: label as string,\n }\n\n const { inputValue, handlePhoneValueChange, inputRef, country, setCountry } = usePhoneInput({\n defaultCountry: defaultCountry,\n value: value || field.value,\n countries: defaultCountries,\n onChange: (data) => {\n if (!disableFormik) {\n helpers.setValue(data.phone)\n } else {\n onChange?.(data.phone)\n }\n },\n })\n\n if (!disableFormik) {\n // Merge Formik-related props if Formik is enabled\n Object.assign(configTextField, {\n ...field,\n error: meta.touched && Boolean(meta.error),\n helperText: ,\n })\n }\n\n return (\n \n \n \n ),\n endAdornment: className?.includes(FieldClasses.locked) ? (\n \n \n \n ) : null,\n }}\n sx={MuiTextFieldSX}\n />\n )\n}\n\nconst CountrySelect: FC = ({ country, setCountry, disabled }) => (\n setCountry(e.target.value as CountryIso2)}\n renderValue={(value) => }>\n {defaultCountries.map((c) => {\n const country = parseCountry(c)\n return (\n \n \n {country.name}\n +{country.dialCode}\n \n )\n })}\n \n)\n\nexport default PhoneNumberField\n","import LoadingButton from '@mui/lab/LoadingButton'\nimport { Box, Typography } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { FC } from 'react'\nimport { useGoogleReCaptcha } from 'react-google-recaptcha-v3'\nimport { Trans, useTranslation } from 'react-i18next'\nimport { MutateFunction } from 'react-query'\nimport { Link } from 'react-router-dom'\n//@ts-ignore\nimport * as Yup from 'yup'\n\nimport { SignupParams, SignupResponse } from '@/api/auth/signup'\nimport { PHONE_NUMNER_E164_REGEX } from '@/api/constants'\nimport { useGetLatestTerms } from '@/api/terms/get'\nimport { ServerError } from '@/api/types'\nimport Checkbox from '@/common/components/Inputs/Checkbox'\nimport PasswordField from '@/common/components/Inputs/PasswordField'\nimport PhoneNumberField from '@/common/components/Inputs/PhoneNumberField'\nimport TextField from '@/common/components/Inputs/TextFieldV2'\nimport PasswordStrengthEvaluation from '@/pages/Settings/Admins/PasswordStrengthEvaluation'\nimport { theme } from '@/theme/theme'\n\nconst SignUpForm: FC<{ signupFunction: MutateFunction }> = ({\n signupFunction,\n}) => {\n const { t } = useTranslation()\n const { executeRecaptcha } = useGoogleReCaptcha()\n const { data: latestTerms } = useGetLatestTerms()\n\n const handleSubmit = async (\n values: {\n organizationName: string\n organizationDomain: string\n promoCode: string\n fullName: string\n email: string\n phoneNumber: string\n acceptTerms: boolean\n password: string\n },\n { setFieldError }: { setFieldError: (field: string, message: string | undefined) => void }\n ) => {\n try {\n const recaptcha = (executeRecaptcha && (await executeRecaptcha('signup'))) || ''\n await signupFunction({\n username: values.email,\n full_name: values.fullName,\n password: values.password,\n company_domains: [values.organizationDomain],\n recaptcha,\n company_name: values.organizationName,\n phone_number: values.phoneNumber,\n promo_code: values.promoCode,\n accept_terms: values.acceptTerms,\n terms: latestTerms?._id as string,\n })\n } catch (e) {\n if ((e as ServerError).response.data.message === 'A user with this username already exists: ' + values.email)\n setFieldError('email', 'A user with this email already exists')\n if (\n (e as ServerError).response.data.message ===\n 'Failed to sign up new user, one or more domains are already registered'\n )\n setFieldError('organizationDomain', 'This domain is already registered')\n if ((e as ServerError).response.data.message === 'Promo code is invalid or expired')\n setFieldError('promoCode', 'Promo code is invalid or expired')\n }\n }\n const initialValues = {\n organizationName: '',\n organizationDomain: '',\n promoCode: '',\n fullName: '',\n email: '',\n phoneNumber: '',\n acceptTerms: false,\n password: '',\n confirmPassword: '',\n }\n const validationSchema = Yup.object().shape({\n organizationName: Yup.string().required(t('signup.errors.missingCompanyName')),\n organizationDomain: Yup.string().required(t('signup.errors.missingDomain')),\n fullName: Yup.string().required(t('signup.errors.missingFullName')),\n email: Yup.string().email(t('signup.errors.invalidEmail')).required(t('signup.errors.missingEmail')),\n phoneNumber: Yup.string()\n .matches(PHONE_NUMNER_E164_REGEX, t('signup.errors.invalidPhone'))\n .required(t('signup.errors.missingPhone')),\n acceptTerms: Yup.boolean().oneOf([true]),\n password: Yup.string().required(t('signup.errors.missingPassword')),\n confirmPassword: Yup.string().test(\n 'confirm-new-password-check',\n t('signup.errors.passwordsDontMatch'),\n function (this: Yup.TestContext, value: string | undefined) {\n const { password } = this.parent\n if (!password && !value) return true\n return value === password || this.createError({ message: \"Passwords don't match\" })\n }\n ),\n })\n return (\n \n {({ isSubmitting, isValid, dirty, values }) => (\n
      \n \n \n {t('signup.signup')}\n \n {t('signup.organizationDetails')}\n \n \n \n \n \n {t('signup.adminDetails')}\n \n \n \n {}} />\n \n \n \n \n \n {!!values.password && }\n \n \n \n {t('signup.signup')}\n \n \n \n \n ),\n }}\n />\n \n \n
      \n )}\n
      \n )\n}\n\nconst termsLable = (\n \n \n ),\n 2: (\n \n ),\n }}\n />\n \n)\nexport default SignUpForm\n","import { Box, Button, Typography } from '@mui/material'\nimport { FC } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useNavigate } from 'react-router-dom'\n\nimport successImage from '@/assets/images/auth/success.svg'\nimport { theme } from '@/theme/theme'\n\nconst SignUpSuccess: FC = () => {\n const { t } = useTranslation()\n const navigateTo = useNavigate()\n return (\n \n \n {t('signup.success')}\n \n {t('signup.successDescription')}\n \n \"success\"\n \n \n \n \n \n )\n}\nexport default SignUpSuccess\n","import { FC } from 'react'\n\nimport { useSignup } from '@/api/auth/signup'\nimport FutureFormWrapper from '@/common/components/Layout/FutureFormWrapper'\nimport SignUpForm from './SignUpForm'\nimport SignUpSuccess from './SignUpSuccess'\n\nconst SignUpPage: FC = () => {\n const [signup, { isSuccess }] = useSignup()\n\n return {isSuccess ? : }\n}\n\nexport default SignUpPage\n","import axios from 'axios'\nimport { API_URL } from '../constants'\nimport { useMutation, useQueryCache } from 'react-query'\nimport { ServerError } from '../types'\n\nimport { CurrentUser } from '../profile/current-user'\n\ntype LoginCredentials = {\n username: string\n password: string\n recaptcha: string\n}\n\nasync function login(credentials: LoginCredentials): Promise {\n const url = `${API_URL}/auth/login/`\n const { data } = await axios.post(url, { ...credentials }, { withCredentials: true })\n return data\n}\n\nexport function useLogin() {\n const queryCache = useQueryCache()\n return useMutation(login, {\n throwOnError: true,\n onSuccess: (data) => {\n if (data?.username && !data?.mfa) {\n queryCache.invalidateQueries('user')\n }\n },\n })\n}\n","import LoadingButton from '@mui/lab/LoadingButton'\nimport { Box, Typography } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { FC, useEffect, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { Link } from 'react-router-dom'\n//@ts-ignore\nimport * as Yup from 'yup'\n\nimport { getErrorMessage } from '@/api/utils/get-error'\nimport PasswordField from '@/common/components/Inputs/PasswordField'\nimport TextField from '@/common/components/Inputs/TextFieldV2'\nimport { detectAutofill } from '@/common/utils/detectAutofill-utils'\nimport { theme } from '@/theme/theme'\n\ntype LoginProps = {\n handleLogin: ({ username, password }: { username: string; password: string }) => Promise\n isLoading: boolean\n}\n\nconst Login: FC = ({ handleLogin, isLoading }) => {\n const { t } = useTranslation()\n const [autofilled, setAutofilled] = useState(false)\n const handleSubmit = async (\n values: { username: string; password: string },\n { setFieldError }: { setFieldError: (field: string, message: string | undefined) => void }\n ) => {\n try {\n await handleLogin(values)\n } catch (e) {\n if (getErrorMessage(e) === 'User has no authorized clients') setFieldError('username', t('login.errors.inactive'))\n else if (getErrorMessage(e) === 'User is not activated') setFieldError('username', t('login.errors.notActivated'))\n else setFieldError('password', t('login.errors.incorrect'))\n }\n }\n\n const updateAutofillState = async () => {\n const isAutofield =\n (await detectAutofill(document.querySelector('input[name=\"username\"]') as HTMLInputElement)) &&\n (await detectAutofill(document.querySelector('input[name=\"password\"]') as HTMLInputElement))\n setAutofilled(isAutofield)\n }\n updateAutofillState()\n\n const initialValues = {\n username: (document.querySelector('input[name=\"username\"]') as HTMLInputElement)?.value || '',\n password: (document.querySelector('input[name=\"password\"]') as HTMLInputElement)?.value || '',\n }\n const validationSchema = Yup.object().shape({\n username: Yup.string().email('Invalid email').required('Field required'),\n password: Yup.string().required('Field required'),\n })\n\n return (\n \n \n {({ isSubmitting, isValid, dirty }) => {\n useEffect(() => {\n if (dirty) setAutofilled(false)\n }, [dirty])\n return (\n
      \n \n \n {t('login.signIn')}\n \n \n \n \n \n \n {t('login.forgotPassword')}\n \n \n \n {t('login.signIn')}\n \n \n \n {t('login.noAccount')}\n \n {t('login.signUp')}\n \n \n \n
      \n )\n }}\n
      \n
      \n )\n}\n\nexport default Login\n","import LoadingButton from '@mui/lab/LoadingButton'\nimport { Box, Link, Typography } from '@mui/material'\nimport { Form, Formik } from 'formik'\nimport { FC } from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\n//@ts-ignore\nimport * as Yup from 'yup'\n\nimport { useMFAVerifyLogin } from '@/api/auth/mfa-verify'\nimport EmailResendTimer from '@/common/components/EmailResend'\nimport TextField from '@/common/components/Inputs/TextFieldV2'\nimport { theme } from '@/theme/theme'\nimport { useNavigate } from 'react-router-dom'\n\ntype MFAProps = { username: string; resendMFA: () => void; MFAType: 'email' | 'app' }\n\nconst MFA: FC = ({ username, resendMFA, MFAType }) => {\n const { t } = useTranslation()\n const { mutateAsync: mfaVerify } = useMFAVerifyLogin()\n const navigateTo = useNavigate()\n\n const handleSubmit = async (\n values: any,\n { setFieldError }: { setFieldError: (field: string, message: string | undefined) => void }\n ) => {\n try {\n await mfaVerify({ token: values.token })\n navigateTo('./')\n } catch (error) {\n setFieldError('token', t('mfa.errors.invalidOrExpired'))\n }\n }\n\n const validationSchema = Yup.object().shape({\n token: Yup.string().required('Field required'),\n })\n\n const initialValues = { token: '' }\n\n return (\n \n \n {({ isSubmitting, isValid, dirty }) => (\n
      \n \n \n {t('mfa.title')}\n \n \n {t(MFAType === 'email' ? 'mfa.enterCodeDescriptionEmail' : 'mfa.enterCodeDescriptionApp', { username })}\n \n \n \n \n {MFAType === 'email' && }\n \n \n {t('mfa.continue')}\n \n \n \n \n ),\n }}\n />\n \n \n
      \n )}\n
      \n
      \n )\n}\n\nexport default MFA\n","export default \"__VITE_ASSET__b1013c12__\"","import { Box, Typography } from '@mui/material'\nimport { Dispatch, FC, SetStateAction } from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\n\nimport lockedBouncerImage from '@/assets/images/auth/locked_bouncer.svg'\nimport { theme } from '@/theme/theme'\n\nconst UserLocked: FC<{ username: string; setUserLocked: Dispatch> }> = ({\n username,\n setUserLocked,\n}) => {\n const { t } = useTranslation()\n return (\n \n \n {t('userLocked.userLocked')}\n \n \n ,\n }}\n values={{ username: username }}\n />\n \n \n \"bouncer\"\n \n \n setUserLocked(false)}\n component=\"span\"\n color={theme.palette.blue[900]}\n fontWeight={theme.typography.fontWeightSemiBold}\n sx={{ cursor: 'pointer' }}\n />\n ),\n }}\n />\n \n \n )\n}\n\nexport default UserLocked\n","import FutureFormWrapper from '@/common/components/Layout/FutureFormWrapper'\nimport { FC, useState } from 'react'\nimport { useGoogleReCaptcha } from 'react-google-recaptcha-v3'\n\nimport { useLogin } from '@/api/auth/login'\nimport Login from './Login'\nimport MFA from './MFA'\nimport UserLocked from '../UserLocked'\nimport { ServerError } from '@/api/types'\nimport { useNavigate } from 'react-router-dom'\n\nconst LoginPage: FC = () => {\n const [login, { isLoading }] = useLogin()\n const { executeRecaptcha } = useGoogleReCaptcha()\n const [MFAType, setMFAType] = useState<'email' | 'app' | undefined>(undefined)\n const [username, setUsername] = useState('')\n const [password, setPassword] = useState('')\n const [userLocked, setUserLocked] = useState(false)\n\n const navigateTo = useNavigate()\n\n const handleLogin = async (formValues: { username: string; password: string }) => {\n try {\n setUsername(formValues.username)\n setPassword(formValues.password)\n const recaptcha = (executeRecaptcha && (await executeRecaptcha('login'))) || ''\n const data = await login({ ...formValues, recaptcha })\n if (data?.mfa_type) {\n setMFAType(data.mfa_type)\n } else {\n navigateTo('/mfa-setup')\n }\n } catch (error) {\n if ((error as ServerError).response.data.message === 'User locked') setUserLocked(true)\n else throw error\n }\n }\n\n const resendMFA = async () => {\n const recaptcha = (executeRecaptcha && (await executeRecaptcha('login'))) || ''\n await login({ ...{ username, password }, recaptcha })\n }\n\n return (\n \n {userLocked ? (\n \n ) : MFAType ? (\n \n ) : (\n \n )}\n \n )\n}\nexport default LoginPage\n","import axios from \"axios\";\nimport { API_URL } from \"../constants\";\nimport { useMutation } from \"react-query\";\nimport { ServerError } from \"../types\";\n\nexport async function unlockUser(token: string): Promise {\n try {\n await axios.post(`${API_URL}/auth/unlock-user/`, { token });\n return true;\n } catch (error) {\n return false;\n }\n}\n\nexport function useUnlockUser() {\n return useMutation(unlockUser);\n}\n","export default \"__VITE_ASSET__ae902300__\"","import { useLocation } from \"react-router-dom\";\n\nexport function useUrlQuery() {\n return new URLSearchParams(useLocation().search);\n}\n\nexport function useUrlSearchQuery() {\n const searchQuery = useLocation().search.replace(\"?\", \"\");\n\n if (searchQuery === \"\") return {};\n\n const parsedSearchQuery = searchQuery\n .split(\"&\")\n .map((pair) => pair.split(\"=\"))\n .reduce((acc, [key, value]) => {\n acc[decodeURIComponent(key)] = decodeURIComponent(value);\n return acc;\n }, {});\n\n return parsedSearchQuery;\n}\n","import { Box, Button, Typography } from '@mui/material'\nimport { FC, useEffect } from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\nimport { useNavigate } from 'react-router-dom'\n\nimport { useUnlockUser } from '@/api/auth/unlock-user'\nimport unlockedBouncerImage from '@/assets/images/auth/unlocked_bouncer.svg'\nimport FutureFormWrapper from '@/common/components/Layout/FutureFormWrapper'\nimport { useUrlQuery } from '@/common/hooks/useUrlQuery'\nimport { theme } from '@/theme/theme'\n\nconst UserUnlockedPage: FC = () => {\n const { t } = useTranslation()\n const navigateTo = useNavigate()\n const urlQuery = useUrlQuery()\n const [unlockUser] = useUnlockUser()\n const token = urlQuery.get('token')\n\n useEffect(() => {\n token && unlockUser(token)\n }, [])\n\n return (\n \n \n \n {t('userUnlocked.userUnlocked')}\n \n \n ,\n }}\n />\n \n \n \"bouncer\"\n \n \n \n \n \n \n )\n}\nexport default UserUnlockedPage\n","import { useMutation } from '@tanstack/react-query'\nimport axios from 'axios'\nimport { API_URL } from '../constants'\n\nexport type ActivateAccountParams = {\n token: string\n password?: string\n accept_terms: boolean\n terms: string\n}\n\nexport async function activateAccount(params: ActivateAccountParams): Promise {\n const url = `${API_URL}/auth/activate-account/`\n\n try {\n await await axios.post(url, params, { withCredentials: true })\n return true\n } catch (error) {\n return false\n }\n}\n\nexport function useActivateAccount() {\n return useMutation({ mutationFn: activateAccount })\n}\n","import { faCheck, faX } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport { useEffect, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useNavigate } from 'react-router-dom'\nimport { Avatar, Button, Container, Paper, Typography } from '@mui/material'\nimport { useActivateAccount } from '@/api/auth/activate-account'\nimport { useUrlQuery } from '@/common/hooks/useUrlQuery'\n\nexport default function VerifyEmail() {\n const classes = useStyles()\n const { t } = useTranslation()\n const urlQuery = useUrlQuery()\n const navigateTo = useNavigate()\n const { mutateAsync: activateAccount } = useActivateAccount()\n const [isEmailValid, setEmailValid] = useState(false)\n\n const token = urlQuery.get('token')\n\n useEffect(() => {\n const verifyToken = async (token: string) => {\n setEmailValid((await activateAccount({ token })) ?? false)\n }\n if (token) {\n verifyToken(token)\n }\n }, [activateAccount, token])\n\n return (\n \n \n {isEmailValid ? (\n \n \n \n ) : (\n \n \n \n )}\n
      \n {t(isEmailValid ? 'verifyEmail.success' : 'verifyEmail.error')}\n \n {t(isEmailValid ? 'verifyEmail.verified' : 'verifyEmail.unverified')}\n \n
      \n \n
      \n
      \n )\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n root: {\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n marginTop: theme.spacing(12),\n padding: theme.spacing(4),\n },\n textContainer: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(6),\n },\n avatar: {\n margin: theme.spacing(1),\n backgroundColor: theme.palette.success.main,\n },\n avatarError: {\n margin: theme.spacing(1),\n backgroundColor: theme.palette.error.main,\n },\n })\n)\n","import { API_URL } from '@/api/constants'\nimport { DefinedInitialDataOptions, useQuery } from '@tanstack/react-query'\nimport { PhishingSimulation } from '@/types/phishingSimulations'\nimport axios from 'axios'\n\nconst getCampaignAssets = async (id: string | undefined): Promise => {\n const url = `${API_URL}/campaigns/${id}/assets/`\n const { data } = await axios.get(url, { withCredentials: true })\n\n return data\n}\n\nexport const useCampaignAssets = (\n id: string | undefined,\n options?: Partial>\n) => {\n return useQuery({\n queryKey: ['campaign', 'assets', id],\n queryFn: () => getCampaignAssets(id),\n enabled: !!id,\n ...options,\n })\n}\n","import axios from 'axios'\n\nimport { API_URL } from '../constants'\nimport { useMutation } from '@tanstack/react-query'\n\nconst getCampaignReport = async (id: string): Promise<{ data: Blob; filename: string }> => {\n const url = `${API_URL}/campaigns/${id}/report/`\n const { headers, data } = await axios.get(url, {\n withCredentials: true,\n responseType: 'blob',\n })\n\n let filename = 'report.pdf'\n const contentDisposition = headers['content-disposition']\n const match = contentDisposition?.match(/filename=\"([^\"]+)\"/i)\n if (match && match[1]) {\n filename = match[1]\n }\n\n return { data, filename }\n}\n\nexport const useGetCampaignReport = (onError: (error: Error) => void) => {\n return useMutation({\n mutationFn: getCampaignReport,\n onSuccess: async ({ data, filename }) => {\n const decodedFilename = decodeURIComponent(filename)\n const link = document.createElement('a')\n link.href = URL.createObjectURL(data)\n link.download = decodedFilename\n link.click()\n URL.revokeObjectURL(link.href)\n },\n onError: (error) => {\n onError && onError(error)\n },\n })\n}\n","import { API_URL } from '@/api/constants'\nimport { paramsSerializer } from '@/api/utils/serialize-array'\nimport { Campaign, CampaignListItem, CampaignListQuery } from '@/types/campaigns'\nimport { PagedResult } from '@/types/common'\nimport { DefinedInitialDataOptions, keepPreviousData, useQuery } from '@tanstack/react-query'\nimport axios from 'axios'\n\nconst getCampaign = async (id: string | undefined) => {\n const url = `${API_URL}/campaigns/${id}/`\n const { data } = await axios.get(url, { withCredentials: true })\n\n return data\n}\n\nconst getCampaigns = async (params: CampaignListQuery) => {\n const url = `${API_URL}/campaigns/`\n const { data } = await axios.get(url, {\n withCredentials: true,\n params,\n paramsSerializer,\n })\n\n return data\n}\n\nexport const useCampaign = (id: string | undefined, options?: Partial>) => {\n return useQuery({\n queryKey: ['campaigns', id],\n queryFn: () => getCampaign(id),\n enabled: !!id,\n ...options,\n })\n}\n\nexport const useCampaigns = (queryParams: CampaignListQuery) => {\n return useQuery>({\n queryKey: ['campaigns', queryParams],\n queryFn: () => getCampaigns(queryParams),\n // refetchInterval: 10_000,\n placeholderData: keepPreviousData, //\n })\n}\n","import axios from 'axios'\nimport { API_URL } from '@/api/constants'\nimport { DefinedInitialDataOptions, keepPreviousData, useQuery } from '@tanstack/react-query'\nimport { CampaignUser } from '@/types/campaigns'\nimport { PagedResult, PagedQuery } from '@/types/common'\n\nexport type CampaignUsersQuery = PagedQuery & {\n id: string | undefined\n}\n\nconst getCampaignUsers = async (id: string | undefined, limit: number, skip: number) => {\n const { data } = await axios.get(`${API_URL}/campaigns/${id}/users/`, {\n params: { ...(skip && { skip }), ...(limit && { limit }) },\n withCredentials: true,\n })\n\n return data\n}\n\nexport const useCampaignUsers = (\n { id, limit = 10, skip = 0 }: CampaignUsersQuery,\n options?: Partial>>\n) => {\n return useQuery>({\n queryKey: ['campaign', id, limit, skip],\n queryFn: () => getCampaignUsers(id, limit, skip),\n enabled: !!id,\n placeholderData: keepPreviousData,\n ...options,\n })\n}\n","import { keepPreviousData, useQuery } from '@tanstack/react-query'\nimport axios from 'axios'\n\nimport { PagedResult } from '@/types/common'\nimport { API_URL } from '../constants'\nimport { paramsSerializer } from '../utils/serialize-array'\nimport { GroupListItem, GroupsListQuery } from '@/types/groups'\n\nconst getGroups = async (params: GroupsListQuery) => {\n const url = `${API_URL}/groups/`\n const { data } = await axios.get(url, {\n withCredentials: true,\n params,\n paramsSerializer,\n })\n\n return data\n}\n\nexport const useGroups = (query: GroupsListQuery) => {\n return useQuery>({\n queryKey: ['groups', query],\n queryFn: () => getGroups(query),\n placeholderData: keepPreviousData,\n })\n}\n","import useLottie from '@/common/hooks/useLottie'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport { FC } from 'react'\n\nimport simulationLaunchAnimationData from '@/assets/lottie/rocketLaunch.json'\n\nconst FeedbackAnimation: FC<{ animationData?: any }> = ({ animationData = simulationLaunchAnimationData }) => {\n const classes = useStyles()\n const { LottieAnimation } = useLottie({\n animationData: animationData,\n width: document.body.clientWidth,\n height: document.body.clientHeight,\n options: {\n loop: false,\n autoplay: true,\n animationData: animationData,\n rendererSettings: {\n preserveAspectRatio: 'xMidYMid slice',\n },\n },\n })\n return
      {LottieAnimation}
      \n}\n\nconst useStyles = makeStyles(() =>\n createStyles({\n lottieContainer: {\n position: 'fixed',\n width: '100%',\n height: '100%',\n bottom: '0px',\n left: '0px',\n zIndex: 1202,\n pointerEvents: 'none',\n },\n })\n)\n\nexport default FeedbackAnimation\n","import { EducationModule } from '@/api/education-modules/modules'\nimport { theme } from '@/theme/theme'\nimport { Campaign } from '@/types/campaigns'\nimport { PhishingSimulation } from '@/types/phishingSimulations'\nimport { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport {\n faBlockQuestion,\n faBullhorn,\n faHexagon,\n faSwords,\n faWavePulse,\n faClapperboardPlay,\n faGauge,\n faUsers,\n} from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { Box, Divider, Typography, Tooltip, styled } from '@mui/material'\nimport { FC } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { NavLink } from 'react-router-dom'\n\ntype CampainDetailsProps = {\n campaignData: Campaign\n membersData: Campaign\n asset?: EducationModule\n isSimulation?: boolean\n phishingSimulations?: PhishingSimulation[]\n vectors?: string[]\n}\nconst CampaignDetails: FC = ({\n campaignData,\n membersData,\n asset,\n isSimulation = false,\n phishingSimulations = [],\n vectors = [],\n}: CampainDetailsProps) => {\n const { t } = useTranslation()\n\n const vectorText = vectors.map((vector) => t('library.' + vector)).join(', ')\n const hasMultipleVectors = vectors.length > 1\n const difficulties = [...new Set(phishingSimulations?.flatMap((sim) => sim.difficulties) || [])].join(', ')\n\n const assetTypeText = () => {\n if (phishingSimulations?.length > 1) {\n return t('campaignDashboard.package', { simulationCount: phishingSimulations.length })\n }\n return t('campaignDashboard.' + campaignData?.asset_type)\n }\n\n return (\n
      \n \n \n {t('trainingCampaignDashboard.campaignName') + ': '}\n \n \n {campaignData?.name}\n \n \n \n \n \n \n {t('trainingCampaignDashboard.type') + ': '}\n {assetTypeText()}\n \n\n {isSimulation ? (\n <>\n \n \n \n {t('campaignDashboard.attackVector') + ': '}\n \n \n {hasMultipleVectors ? t('campaignDashboard.mixedVectors') : vectorText}\n \n \n \n \n \n \n {t('campaignDashboard.difficulty') + ': '}\n {difficulties}\n \n \n ) : (\n <>\n \n \n \n {t('trainingCampaignDashboard.video') + ': '}\n \n \n {asset?.title}\n \n \n \n \n )}\n {!!asset?.quizzes?.length && (\n <>\n \n \n \n {t('trainingCampaignDashboard.quiz') + ': '}\n \n {(asset?.quizzes ? asset.quizzes[0].questions.length : 0) +\n ' ' +\n t('trainingCampaignDashboard.questions')}\n \n \n \n )}\n \n \n \n {t('trainingCampaignDashboard.totalMembers') + ': '}\n {membersData?.total}\n \n \n \n \n {t('trainingCampaignDashboard.status') + ': '}\n {campaignData?.status_details ? (\n {t('campaigns.statusDetails.' + campaignData?.status_details)}\n ) : (\n {t('trainingCampaignDashboard.' + campaignData?.status)}\n )}\n \n
      \n )\n}\n\nconst StyledDivider = styled(Divider)(() => ({\n margin: '0px 15px',\n borderBottomWidth: '3px',\n borderColor: '#E0EDEF',\n}))\n\nconst KeyTypography = styled(Typography)(() => ({\n fontWeight: theme.typography.fontWeightBold,\n}))\n\nconst DetailBox = styled(Box)(() => ({\n display: 'flex',\n padding: '12px 26px',\n gap: '12px',\n alignItems: 'center',\n}))\n\nexport default CampaignDetails\n","import { useEffect, useRef } from 'react'; // eslint-disable-line no-unused-vars\n\nfunction useInterval(callback: () => void, delay) {\n const savedCallback = useRef<() => void>();\n\n // Remember the latest callback.\n useEffect(() => {\n savedCallback.current = callback;\n }, [callback]);\n\n // Set up the interval.\n useEffect(() => {\n function tick() {\n if (savedCallback.current) savedCallback.current();\n }\n if (delay !== null) {\n let id = setInterval(tick, delay);\n return () => clearInterval(id);\n }\n }, [delay]);\n}\n\nexport default useInterval;\n","import { PagedQuery } from './common'\nimport { Sender } from './phishingSimulations'\n//TODO Find better place for this file\n\n//TODO This should be a const\nexport const PER_USER = 'per_user'\n\nexport enum AssetType {\n training_video = 'training_video',\n phishing_simulation = 'phishing_simulation',\n}\n\nexport enum CampaignStatus {\n pending = 'pending', // before start date\n processing = 'processing', // creating email schedules (system status)\n scheduled = 'scheduled', // schelueles created but no email sent yet (system status)\n in_progress = 'in_progress', // active campaing\n completed = 'completed', // after end date\n canceled = 'canceled', // by user\n error = 'error', // e.g. error in creating email schedules\n}\n\nexport enum CampaignStatusDetails {\n error_members_quota = 'error_members_quota',\n}\n\nexport enum CampaignScore {\n bad = 'bad',\n low = 'low',\n average = 'average',\n excellent = 'excellent',\n}\n\nexport type CampaignDifficulty = '1' | '2' | '3' | '4' | '5'\n\nexport enum AssetAssignmentType {\n targeted = 'targeted',\n single_random = 'single_random',\n random_per_user = 'random_per_user',\n}\n\nexport type Targets = {\n groups: { [id: string]: AssetAssignmentType.single_random | AssetAssignmentType.single_random | 'string' }\n dynamic_groups: { [id: string]: AssetAssignmentType.single_random | AssetAssignmentType.single_random | 'string' }\n offices: { [id: string]: AssetAssignmentType.single_random | AssetAssignmentType.single_random | 'string' }\n users: { [id: string]: AssetAssignmentType.single_random | AssetAssignmentType.single_random | 'string' }\n}\n\nexport enum AssetAssignmentFallback {\n single_random = 'single_random',\n random_per_user = 'random_per_user',\n}\n\nexport type AssetAssignmentLogic = {\n type: AssetAssignmentType\n targets?: Targets\n fallback?: AssetAssignmentFallback\n}\n\nexport type Schedule = {\n start: string\n end: string\n start_tz?: string\n end_tz?: string\n send_on_start?: boolean\n send_over_days?: number\n}\n\nexport type CampaignRequest = {\n name: string\n users: string[]\n offices: string[]\n dynamic_groups: string[]\n groups: string[]\n asset_type: string\n asset_ids: string[]\n asset_metadata?: Record\n asset_assignment_logic: AssetAssignmentLogic\n schedule: Schedule\n is_test?: boolean\n custom_microtraining_urls?: Record\n}\n\nexport type Campaign = CampaignRequest & {\n _id: string\n status: CampaignStatus\n status_details: CampaignStatusDetails\n client_id: string\n users_count: number\n score: number\n bamboohr_training_id: number\n created_by: string\n created_at: string\n updated_at: string\n}\n\nexport type CampaignListItem = {\n _id: string\n name: string\n status: string\n status_details: string\n users_count: number\n asset_type: AssetType\n score: string\n is_test: boolean\n start_date: string\n start_tz: string\n end_date: string\n end_tz: string\n asset_metadata: {\n include_quiz?: boolean\n difficulty?: number\n }\n asset_ids: string[]\n}\n\nexport type CampaignUserEvents = {\n sms_link_click: string | boolean\n email_link_click: string | boolean\n email_open: string | boolean\n submit: string | boolean\n report: string | boolean\n feedback_link_click: string | boolean\n feedback_completed: string | boolean\n feedback_acknowledged: string | boolean\n feedback_tab_closed: string | boolean\n feedback_page_iteration: string | boolean\n show_feedback_tips: string | boolean\n feedback_opened: string | boolean\n training_paused: string | boolean\n training_completed: string | boolean\n training_closed: string | boolean\n training_opened: string | boolean\n inserted_data: string | boolean\n quiz_started: string | boolean\n quiz_paused: string | boolean\n quiz_continued: string | boolean\n quiz_completed: string | boolean\n quiz_answer: string | boolean\n email_reply: string | boolean\n video_page_load: string | boolean\n video_running: string | boolean\n video_tab_blur: string | boolean\n video_tab_focus: string | boolean\n video_tab_close: string | boolean\n subtitle_change: string | boolean\n expired_campaign_link_click: string | boolean\n campaign_started: string | boolean\n campaign_sent: string | boolean\n}\n\nexport type CampaignUser = {\n _id: string\n username: string\n first_name: string\n last_name: string\n member_of: string[]\n campaign_score: number\n events: CampaignUserEvents\n}\n\nexport type MicrotrainingIndicator = {\n selector: string\n title: string\n description: string\n}\n\nexport type CampaignMicrotraining = {\n sender: Sender\n subject: string\n logo: string\n message: {\n html: string\n language: string\n }\n landing_page: {\n html: string\n language: string\n }\n indicators: {\n message: MicrotrainingIndicator[]\n landing_page: MicrotrainingIndicator[]\n }\n token: string\n vector?: string\n}\n\nexport enum CampaignQuerySort {\n start_date = 'start_date',\n end_date = 'end_date',\n name = 'name',\n users_count = 'users_count',\n score = 'score',\n}\n\nexport type CampaignListQuery = PagedQuery & {\n name: string\n start_date: string\n end_date: string\n score: CampaignScore[]\n status: CampaignStatus[]\n asset_type: AssetType[]\n difficulty: CampaignDifficulty[]\n is_test: boolean[]\n}\n","import { Box, Skeleton, Typography, styled } from '@mui/material'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport moment from 'moment'\nimport { FC, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\n\nimport useInterval from '@/common/hooks/useInterval'\nimport { AssetType, Campaign, CampaignStatus } from '@/types/campaigns'\nimport { theme } from '@/theme/theme'\nimport { US_DATE_TIME_WITH_MONTH_NAME } from '@/api/constants'\n\ntype CountdownProps = {\n campaign: Campaign\n}\n\nconst Countdown: FC = ({ campaign }) => {\n const classes = useStyles()\n const { t } = useTranslation()\n\n const startsAt = moment(campaign?.schedule.start)\n const endsAt = moment(campaign?.schedule.end)\n\n const completed = moment().diff(startsAt, 'seconds')\n const length = endsAt.diff(startsAt, 'seconds')\n const secondsRemaining = length - completed\n const hasEnded = moment().isAfter(endsAt)\n const hasStarted = moment().isAfter(startsAt)\n\n const [timeRemaining, setTimeRemaining] = useState({\n days: 0,\n hours: 0,\n minutes: 0,\n seconds: 0,\n })\n\n //TODO Refactor the Countdown component. It consisnt of lots of logic and the real Coundown in only part of it.\n if (campaign?.status === CampaignStatus.canceled) {\n return (\n \n \n {t('activeBaseline.countdown.originalSchedule')}\n \n \n \n {t('activeBaseline.countdown.startDate')}\n \n \n {campaign ? moment(startsAt).format(US_DATE_TIME_WITH_MONTH_NAME) : }\n \n \n \n \n {' '}\n {t('activeBaseline.countdown.endDate')}\n \n \n {campaign ? moment(endsAt).format(US_DATE_TIME_WITH_MONTH_NAME) : }\n \n \n\n
      \n \n \n {t('activeBaseline.countdown.canceledOn')}\n \n \n {campaign ? moment(campaign.updated_at).format(US_DATE_TIME_WITH_MONTH_NAME) : }\n \n \n \n )\n }\n\n const convertToTime = (secondsRemaining: number) => {\n const days = Math.floor(secondsRemaining / (3600 * 24))\n const hours = Math.floor((secondsRemaining % (3600 * 24)) / 3600)\n const minutes = Math.floor((secondsRemaining % 3600) / 60)\n const seconds = Math.floor(secondsRemaining % 60)\n\n return { days, hours, minutes, seconds }\n }\n\n const getEndingTitle = () => {\n if (hasEnded) {\n return campaign.asset_type === AssetType.training_video\n ? t('activeBaseline.countdown.campaignEnded')\n : t('activeBaseline.countdown.ended')\n }\n\n return t('activeBaseline.countdown.endsIn')\n }\n\n useInterval(() => {\n setTimeRemaining(convertToTime(secondsRemaining))\n }, 1000)\n\n return (\n \n \n {hasStarted ? t('activeBaseline.countdown.started') : t('activeBaseline.countdown.scheduled')}\n \n \n {campaign ? moment(startsAt).format(US_DATE_TIME_WITH_MONTH_NAME) : }\n \n
      \n {getEndingTitle()}\n {!campaign ? (\n \n ) : secondsRemaining > 0 ? (\n \n
      \n {timeRemaining.days}\n \n {t('activeBaseline.countdown.time.day', {\n count: timeRemaining.days,\n })}\n \n
      \n
      \n {timeRemaining.hours}\n \n {t('activeBaseline.countdown.time.hour', {\n count: timeRemaining.hours,\n })}\n \n
      \n
      \n {timeRemaining.minutes}\n \n {t('activeBaseline.countdown.time.minute', {\n count: timeRemaining.minutes,\n })}\n \n
      \n\n
      \n {timeRemaining.seconds}\n \n {t('activeBaseline.countdown.time.second', {\n count: timeRemaining.seconds,\n })}\n \n
      \n
      \n ) : (\n \n {moment(endsAt).format(US_DATE_TIME_WITH_MONTH_NAME)}\n \n )}\n \n )\n}\n\nconst CountTypography = styled(Typography)(() => ({\n fontWeight: 'bold',\n fontSize: '22px',\n color: 'inherit',\n}))\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n root: {\n height: '100%',\n width: '100%',\n padding: theme.spacing(2),\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n },\n counter: {\n display: 'flex',\n justifyContent: 'space-evenly',\n width: '100%',\n gap: theme.spacing(1),\n marginTop: theme.spacing(1),\n marginBottom: theme.spacing(2),\n },\n countContainer: {\n textAlign: 'center',\n },\n divider: {\n height: 1,\n width: '70%',\n background: theme.palette.divider,\n margin: theme.spacing(1, 0),\n },\n date: {\n textTransform: 'uppercase',\n },\n })\n)\n\nexport default Countdown\n","import React from \"react\";\nimport { Typography } from \"@mui/material\";\nimport { useTranslation } from \"react-i18next\";\nimport makeStyles from \"@mui/styles/makeStyles\";\nimport createStyles from \"@mui/styles/createStyles\";\n\nexport default function NoResultsContainer({\n text,\n image,\n}: {\n text: string;\n image?: string;\n}) {\n const classes = useStyles();\n const { t } = useTranslation();\n return (\n
      \n {image && {text}}\n \n {t(text)}\n \n
      \n );\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n root: {\n height: \"100%\",\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n })\n);\n","import { IconProp } from '@fortawesome/fontawesome-svg-core'\nimport { faCircleInfo } from '@fortawesome/pro-light-svg-icons'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { IconButton, Tooltip, TooltipProps, Typography } from '@mui/material'\nimport createStyles from '@mui/styles/createStyles'\nimport makeStyles from '@mui/styles/makeStyles'\nimport { FC } from 'react'\n\nimport { theme } from '@/theme/theme'\n\ninterface InfoTooltipProps extends Omit {\n title: string | JSX.Element\n fontSize?: number\n color?: string\n}\nconst InfoTooltip: FC = ({ title, fontSize, color, ...rest }) => {\n const classes = useStyles()\n return (\n \n {title}\n \n }\n {...rest}>\n \n \n \n \n )\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n icon: {\n padding: theme.spacing(0.2, 0.8),\n color: theme.palette.text.secondary,\n },\n })\n)\nexport default InfoTooltip\n","import React, { useMemo, memo } from \"react\";\nimport { Typography, useTheme } from \"@mui/material\";\nimport { useTranslation } from \"react-i18next\";\nimport NoResultsContainer from \"../NoResultsContainer/NoResultsContainer\";\nimport { User } from \"../../../api/users/users\";\nimport { Theme } from \"@mui/material/styles\";\nimport createStyles from \"@mui/styles/createStyles\";\nimport makeStyles from \"@mui/styles/makeStyles\";\nimport GaugeChart from \"react-gauge-chart\";\nimport InfoTooltip from \"../InfoTooltip/InfoTooltip\";\n\nexport default memo(function GaugeScoremeter({\n score,\n hideTitle = false,\n}: {\n score: User[\"awareness_score\"];\n hideTitle?: boolean;\n}) {\n const theme = useTheme();\n const classes = useStyles();\n const { t } = useTranslation();\n\n const levels = useMemo(() => {\n return [\n {\n label: t(\"awarenessMeter.bad\"),\n color: theme.palette.error.main,\n },\n {\n label: t(\"awarenessMeter.low\"),\n color: theme.palette.warning.main,\n },\n {\n label: t(\"awarenessMeter.average\"),\n color: theme.palette.warning.light,\n },\n {\n label: t(\"awarenessMeter.excellent\"),\n color: theme.palette.success.main,\n },\n ];\n }, [\n t,\n theme.palette.error.main,\n theme.palette.success.main,\n theme.palette.warning.light,\n theme.palette.warning.main,\n ]);\n\n const percentage = useMemo(() => (score || 0) / 100, [score]);\n\n return score >= 0 ? (\n
      \n {hideTitle ? null : (\n
      \n \n {t(\"awarenessMeter.title\")}\n \n \n
      \n )}\n
      \n \n
      \n
      \n {levels.map((level) => (\n
      \n
      \n {level.label}\n
      \n ))}\n
      \n
      \n ) : (\n \n );\n});\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n root: {\n // paddingBottom: theme.spacing(1),\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n },\n title: {\n // marginTop: theme.spacing(0.5),\n marginRight: theme.spacing(0.5),\n },\n titleContainer: {\n display: \"flex\",\n alignItems: \"center\",\n alignSelf: \"flex-start\",\n marginBottom: theme.spacing(3),\n },\n chartContainer: {\n maxWidth: 400,\n },\n legendContainer: {\n display: \"flex\",\n justifyContent: \"space-evenly\",\n width: \"100%\",\n maxWidth: 500,\n },\n legendItem: {\n display: \"flex\",\n alignItems: \"center\",\n },\n dot: {\n marginRight: theme.spacing(1),\n borderRadius: \"50%\",\n height: 12,\n width: 12,\n },\n })\n);\n\n// {/**/}\n","import React from \"react\";\nimport { Theme } from \"@mui/material/styles\";\nimport createStyles from \"@mui/styles/createStyles\";\nimport makeStyles from \"@mui/styles/makeStyles\";\nimport { CircularProgress, Paper } from \"@mui/material\";\n\ntype LoadingContainerProps = {\n height?: number;\n container?: \"div\" | \"paper\";\n};\n\nexport default function LoadingContainer({\n height,\n container = \"div\",\n}: LoadingContainerProps) {\n const classes = useStyles({ height });\n return container === \"div\" ? (\n
      \n \n
      \n ) : (\n \n \n \n );\n}\n\nconst useStyles = makeStyles((theme) =>\n createStyles({\n root: {\n height: ({ height }) => (height ? height : \"100%\"),\n width: \"100%\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n })\n);\n","export enum PhishingSimulationState {\n Published = 'published',\n Archived = 'archived',\n Draft = 'draft',\n}\n\nexport enum PhishingSimulationVector {\n Email = 'email',\n SMS = 'sms',\n WhatsApp = 'whatsapp',\n}\n\nexport type PhishingIndicator = {\n selector: string\n difficulty: number\n title: {\n [key: string]: string\n }\n description: {\n [key: string]: string\n }\n}\n\ntype EmailContent = {\n message: string\n landing_page: string\n}\n\nexport type Sender = {\n name: string\n mailbox: string\n subdomain: string\n}\n\ntype Placeholders = {\n message: string[]\n landing_page: string[]\n}\n\nexport type Languages = {\n message: string[]\n landing_page: string[]\n}\n\nexport type CoverImages = {\n message: string\n landing_page: string\n microtraining: string\n}\n\nexport type PhishingSimulationRequest = {\n name: string\n subject: string\n sender: Sender\n html_contents: EmailContent\n placeholders: Placeholders\n phishing_indicators: {\n message: PhishingIndicator[]\n landing_page: PhishingIndicator[]\n }\n languages: Languages\n cover_images: CoverImages\n vectors: PhishingSimulationVector[]\n tags: string[]\n ai_generated: boolean\n is_public: boolean\n difficulties: number[]\n state: PhishingSimulationState\n}\n\nexport type PhishingSimulation = PhishingSimulationRequest & {\n id: string\n organization_id: string\n image_cloudinary_ids: {\n message: string\n landing_page: string\n micro_training: string\n }\n created_by: string\n created_at: string\n updated_at: string\n template_thumbnail?: string\n}\n\n//type PhishingSimulationListItem same as PhishingSimulation\n\nexport type PhishingSimulationPackageRequest = {\n name: string\n simulation_ids: string[]\n}\n\n//TODO : extended.\nexport type PhishingSimulationPackage = PhishingSimulationPackageRequest & {\n id: string\n organization_id: string\n simulations: PhishingSimulation[]\n created_by: string\n created_at: string\n updated_at: string\n}\n\nexport type PhishingSimulationPackageExtended = PhishingSimulationPackage & {\n languages?: Languages\n difficulties?: number[]\n tags?: string[]\n vectors?: PhishingSimulationVector[]\n}\n\nexport type PhishingSimulationPackageUpdateRequest = {\n id: string\n params: Partial\n}\n\nexport type PhishingSimulationAndPackages = PhishingSimulationPackage &\n PhishingSimulation & {\n _id: string\n }\n\nexport type PhishingSimulationAndPackagesRequest = {\n query: {\n skip?: number\n limit?: number\n sort_by?: string\n search?: string\n languages?: string[]\n vectors?: string[]\n tags?: string[]\n cywareness_session?: string\n }\n}\n\nexport type PhishingSimulationAndPackagesResponse = {\n total: number\n results: [\n {\n _id: string\n title: string\n client_id: string\n organization_id: string\n description: string\n thumbnail: string\n tags: string[]\n vectors: string[]\n duration: number\n copyrights: boolean\n languages: string[]\n subtitle_tracks: object\n video_tracks: object\n quizzes: object[]\n updated_at: string\n additional_resources: object\n }\n ]\n}\n","import { Theme } from '@mui/material/styles'\nimport makeStyles from '@mui/styles/makeStyles'\n\ntype ChromeProps = {\n screenshot?: string\n htmlDoc?: string\n}\n\ntype GmailProps = {\n sender: string\n senderName: string\n htmlDoc: string\n subject: string\n}\n\nexport const Chrome = ({ screenshot, htmlDoc, ...props }: ChromeProps) => (\n \n \n \n \n \n \n {/* */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {screenshot && }\n \n {!screenshot && (\n \n {/*{htmlDoc}*/}\n