@stack-spot/portal-layout 0.0.65 → 1.0.0-dev.1768482785050
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +779 -0
- package/dist/Layout.d.ts +60 -8
- package/dist/Layout.d.ts.map +1 -1
- package/dist/Layout.js +59 -24
- package/dist/Layout.js.map +1 -1
- package/dist/LayoutOverlayManager.d.ts +274 -19
- package/dist/LayoutOverlayManager.d.ts.map +1 -1
- package/dist/LayoutOverlayManager.js +373 -82
- package/dist/LayoutOverlayManager.js.map +1 -1
- package/dist/WelcomeTour.d.ts +2 -0
- package/dist/WelcomeTour.d.ts.map +1 -0
- package/dist/WelcomeTour.js +8 -0
- package/dist/WelcomeTour.js.map +1 -0
- package/dist/components/Backdrop.d.ts +75 -0
- package/dist/components/Backdrop.d.ts.map +1 -0
- package/dist/components/Backdrop.js +69 -0
- package/dist/components/Backdrop.js.map +1 -0
- package/dist/components/Contact/show-contact-modal.d.ts +5 -0
- package/dist/components/Contact/show-contact-modal.d.ts.map +1 -0
- package/dist/components/Contact/show-contact-modal.js +37 -0
- package/dist/components/Contact/show-contact-modal.js.map +1 -0
- package/dist/components/ContactModal.d.ts +1 -0
- package/dist/components/ContactModal.d.ts.map +1 -0
- package/dist/components/ContactModal.js +2 -0
- package/dist/components/ContactModal.js.map +1 -0
- package/dist/components/Dialog.d.ts +54 -7
- package/dist/components/Dialog.d.ts.map +1 -1
- package/dist/components/Dialog.js +8 -2
- package/dist/components/Dialog.js.map +1 -1
- package/dist/components/Header.d.ts +38 -2
- package/dist/components/Header.d.ts.map +1 -1
- package/dist/components/Header.js +9 -4
- package/dist/components/Header.js.map +1 -1
- package/dist/components/NotificationCenter/NotificationPanel.d.ts +3 -0
- package/dist/components/NotificationCenter/NotificationPanel.d.ts.map +1 -0
- package/dist/components/NotificationCenter/NotificationPanel.js +19 -0
- package/dist/components/NotificationCenter/NotificationPanel.js.map +1 -0
- package/dist/components/NotificationCenter/NotificationPanelHeader.d.ts +3 -0
- package/dist/components/NotificationCenter/NotificationPanelHeader.d.ts.map +1 -0
- package/dist/components/NotificationCenter/NotificationPanelHeader.js +16 -0
- package/dist/components/NotificationCenter/NotificationPanelHeader.js.map +1 -0
- package/dist/components/NotificationCenter/NotificationsPanelFooter.d.ts +4 -0
- package/dist/components/NotificationCenter/NotificationsPanelFooter.d.ts.map +1 -0
- package/dist/components/NotificationCenter/NotificationsPanelFooter.js +12 -0
- package/dist/components/NotificationCenter/NotificationsPanelFooter.js.map +1 -0
- package/dist/components/NotificationCenter/dictionary.d.ts +2 -0
- package/dist/components/NotificationCenter/dictionary.d.ts.map +1 -0
- package/dist/components/NotificationCenter/dictionary.js +43 -0
- package/dist/components/NotificationCenter/dictionary.js.map +1 -0
- package/dist/components/NotificationCenter/index.d.ts +2 -0
- package/dist/components/NotificationCenter/index.d.ts.map +1 -0
- package/dist/components/NotificationCenter/index.js +34 -0
- package/dist/components/NotificationCenter/index.js.map +1 -0
- package/dist/components/NotificationCenter/styled.d.ts +3 -0
- package/dist/components/NotificationCenter/styled.d.ts.map +1 -0
- package/dist/components/NotificationCenter/styled.js +74 -0
- package/dist/components/NotificationCenter/styled.js.map +1 -0
- package/dist/components/NotificationCenter/types.d.ts +21 -0
- package/dist/components/NotificationCenter/types.d.ts.map +1 -0
- package/dist/components/NotificationCenter/types.js.map +1 -0
- package/dist/components/NotificationCenter/utils.d.ts +5 -0
- package/dist/components/NotificationCenter/utils.d.ts.map +1 -0
- package/dist/components/NotificationCenter/utils.js +18 -0
- package/dist/components/NotificationCenter/utils.js.map +1 -0
- package/dist/components/OverlayContent.d.ts +27 -1
- package/dist/components/OverlayContent.d.ts.map +1 -1
- package/dist/components/OverlayContent.js +8 -4
- package/dist/components/OverlayContent.js.map +1 -1
- package/dist/components/PortalSwitcher.d.ts +19 -1
- package/dist/components/PortalSwitcher.d.ts.map +1 -1
- package/dist/components/PortalSwitcher.js +16 -31
- package/dist/components/PortalSwitcher.js.map +1 -1
- package/dist/components/PrivacyPolicyMessage/hooks.d.ts +10 -0
- package/dist/components/PrivacyPolicyMessage/hooks.d.ts.map +1 -0
- package/dist/components/PrivacyPolicyMessage/hooks.js +33 -0
- package/dist/components/PrivacyPolicyMessage/hooks.js.map +1 -0
- package/dist/components/PrivacyPolicyMessage/index.d.ts +7 -0
- package/dist/components/PrivacyPolicyMessage/index.d.ts.map +1 -0
- package/dist/components/PrivacyPolicyMessage/index.js +5 -0
- package/dist/components/PrivacyPolicyMessage/index.js.map +1 -0
- package/dist/components/Rate/FeedbackModal.d.ts +8 -0
- package/dist/components/Rate/FeedbackModal.d.ts.map +1 -0
- package/dist/components/Rate/FeedbackModal.js +52 -0
- package/dist/components/Rate/FeedbackModal.js.map +1 -0
- package/dist/components/Rate/hook.d.ts +3 -0
- package/dist/components/Rate/hook.d.ts.map +1 -0
- package/dist/components/Rate/hook.js +48 -0
- package/dist/components/Rate/hook.js.map +1 -0
- package/dist/components/Rate/index.d.ts +10 -0
- package/dist/components/Rate/index.d.ts.map +1 -0
- package/dist/components/Rate/index.js +16 -0
- package/dist/components/Rate/index.js.map +1 -0
- package/dist/components/Rate/on-nps-submit.d.ts +7 -0
- package/dist/components/Rate/on-nps-submit.d.ts.map +1 -0
- package/dist/components/Rate/on-nps-submit.js +8 -0
- package/dist/components/Rate/on-nps-submit.js.map +1 -0
- package/dist/components/Rate/show-rate-us-modals.d.ts +17 -0
- package/dist/components/Rate/show-rate-us-modals.d.ts.map +1 -0
- package/dist/components/Rate/show-rate-us-modals.js +14 -0
- package/dist/components/Rate/show-rate-us-modals.js.map +1 -0
- package/dist/components/Rate/utils.d.ts +2 -0
- package/dist/components/Rate/utils.d.ts.map +1 -0
- package/dist/components/Rate/utils.js +10 -0
- package/dist/components/Rate/utils.js.map +1 -0
- package/dist/components/Toaster.d.ts +35 -0
- package/dist/components/Toaster.d.ts.map +1 -1
- package/dist/components/Toaster.js +32 -4
- package/dist/components/Toaster.js.map +1 -1
- package/dist/components/TypeForm/hook.d.ts +2 -0
- package/dist/components/TypeForm/hook.d.ts.map +1 -0
- package/dist/components/TypeForm/hook.js +11 -0
- package/dist/components/TypeForm/hook.js.map +1 -0
- package/dist/components/TypeForm/index.d.ts +6 -0
- package/dist/components/TypeForm/index.d.ts.map +1 -0
- package/dist/components/TypeForm/index.js +23 -0
- package/dist/components/TypeForm/index.js.map +1 -0
- package/dist/components/TypeForm/show-typeform-modal.d.ts +5 -0
- package/dist/components/TypeForm/show-typeform-modal.d.ts.map +1 -0
- package/dist/components/TypeForm/show-typeform-modal.js +11 -0
- package/dist/components/TypeForm/show-typeform-modal.js.map +1 -0
- package/dist/components/TypeForm/utils.d.ts +2 -0
- package/dist/components/TypeForm/utils.d.ts.map +1 -0
- package/dist/components/TypeForm/utils.js +9 -0
- package/dist/components/TypeForm/utils.js.map +1 -0
- package/dist/components/UserMenu.d.ts +19 -2
- package/dist/components/UserMenu.d.ts.map +1 -1
- package/dist/components/UserMenu.js +12 -6
- package/dist/components/UserMenu.js.map +1 -1
- package/dist/components/error/ErrorBoundary.d.ts +25 -4
- package/dist/components/error/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/error/ErrorBoundary.js +10 -1
- package/dist/components/error/ErrorBoundary.js.map +1 -1
- package/dist/components/error/ErrorManager.d.ts +22 -6
- package/dist/components/error/ErrorManager.d.ts.map +1 -1
- package/dist/components/error/ErrorManager.js +21 -1
- package/dist/components/error/ErrorManager.js.map +1 -1
- package/dist/components/error/SilentErrorBoundary.d.ts +26 -5
- package/dist/components/error/SilentErrorBoundary.d.ts.map +1 -1
- package/dist/components/error/SilentErrorBoundary.js +10 -0
- package/dist/components/error/SilentErrorBoundary.js.map +1 -1
- package/dist/components/menu/MenuContent.d.ts +20 -4
- package/dist/components/menu/MenuContent.d.ts.map +1 -1
- package/dist/components/menu/MenuContent.js +89 -88
- package/dist/components/menu/MenuContent.js.map +1 -1
- package/dist/components/menu/MenuSectionGroup.d.ts +2 -0
- package/dist/components/menu/MenuSectionGroup.d.ts.map +1 -0
- package/dist/components/menu/MenuSectionGroup.js +121 -0
- package/dist/components/menu/MenuSectionGroup.js.map +1 -0
- package/dist/components/menu/MenuSections.d.ts +17 -0
- package/dist/components/menu/MenuSections.d.ts.map +1 -1
- package/dist/components/menu/MenuSections.js +159 -39
- package/dist/components/menu/MenuSections.js.map +1 -1
- package/dist/components/menu/PageSelector.d.ts +5 -0
- package/dist/components/menu/PageSelector.d.ts.map +1 -1
- package/dist/components/menu/PageSelector.js +9 -4
- package/dist/components/menu/PageSelector.js.map +1 -1
- package/dist/components/menu/types.d.ts +219 -8
- package/dist/components/menu/types.d.ts.map +1 -1
- package/dist/components/tour/StepContainer.d.ts +37 -0
- package/dist/components/tour/StepContainer.d.ts.map +1 -0
- package/dist/components/tour/StepContainer.js +51 -0
- package/dist/components/tour/StepContainer.js.map +1 -0
- package/dist/components/tour/StepNavigation.d.ts +29 -0
- package/dist/components/tour/StepNavigation.d.ts.map +1 -0
- package/dist/components/tour/StepNavigation.js +37 -0
- package/dist/components/tour/StepNavigation.js.map +1 -0
- package/dist/components/tour/StepTitle.d.ts +17 -0
- package/dist/components/tour/StepTitle.d.ts.map +1 -0
- package/dist/components/tour/StepTitle.js +10 -0
- package/dist/components/tour/StepTitle.js.map +1 -0
- package/dist/components/tour/hook.d.ts +3 -0
- package/dist/components/tour/hook.d.ts.map +1 -0
- package/dist/components/tour/hook.js +10 -0
- package/dist/components/tour/hook.js.map +1 -0
- package/dist/components/tour/index.d.ts +5 -0
- package/dist/components/tour/index.d.ts.map +1 -0
- package/dist/components/tour/index.js +5 -0
- package/dist/components/tour/index.js.map +1 -0
- package/dist/components/tour/manager.d.ts +34 -0
- package/dist/components/tour/manager.d.ts.map +1 -0
- package/dist/components/tour/manager.js +104 -0
- package/dist/components/tour/manager.js.map +1 -0
- package/dist/components/tour/utils.d.ts +67 -0
- package/dist/components/tour/utils.d.ts.map +1 -0
- package/dist/components/tour/utils.js +60 -0
- package/dist/components/tour/utils.js.map +1 -0
- package/dist/components/user-menu-manager.d.ts +13 -0
- package/dist/components/user-menu-manager.d.ts.map +1 -0
- package/dist/components/user-menu-manager.js +36 -0
- package/dist/components/user-menu-manager.js.map +1 -0
- package/dist/dictionary.d.ts +6 -1
- package/dist/dictionary.d.ts.map +1 -1
- package/dist/dictionary.js +7 -2
- package/dist/dictionary.js.map +1 -1
- package/dist/elements.d.ts +7 -0
- package/dist/elements.d.ts.map +1 -1
- package/dist/elements.js +7 -0
- package/dist/elements.js.map +1 -1
- package/dist/index.d.ts +15 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -8
- package/dist/index.js.map +1 -1
- package/dist/layout.css +190 -35
- package/dist/svg/StarFillWithGradient.d.ts +6 -0
- package/dist/svg/StarFillWithGradient.d.ts.map +1 -0
- package/dist/svg/StarFillWithGradient.js +4 -0
- package/dist/svg/StarFillWithGradient.js.map +1 -0
- package/dist/toaster.d.ts +55 -9
- package/dist/toaster.d.ts.map +1 -1
- package/dist/toaster.js +34 -6
- package/dist/toaster.js.map +1 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +6 -69
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +9 -130
- package/dist/utils.js.map +1 -1
- package/package.dev.json +3 -0
- package/package.json +24 -13
- package/package.stg.json +3 -0
- package/readme.md +147 -0
- package/src/Layout.tsx +166 -58
- package/src/LayoutOverlayManager.tsx +499 -85
- package/src/WelcomeTour.tsx +8 -0
- package/src/components/Backdrop.tsx +116 -0
- package/src/components/Contact/show-contact-modal.tsx +71 -0
- package/src/components/Dialog.tsx +58 -9
- package/src/components/Header.tsx +53 -5
- package/src/components/NotificationCenter/NotificationPanel.tsx +40 -0
- package/src/components/NotificationCenter/NotificationPanelHeader.tsx +53 -0
- package/src/components/NotificationCenter/NotificationsPanelFooter.tsx +25 -0
- package/src/components/NotificationCenter/dictionary.ts +44 -0
- package/src/components/NotificationCenter/index.tsx +58 -0
- package/src/components/NotificationCenter/styled.ts +75 -0
- package/src/components/NotificationCenter/types.ts +24 -0
- package/src/components/NotificationCenter/utils.ts +20 -0
- package/src/components/OverlayContent.tsx +40 -5
- package/src/components/PortalSwitcher.tsx +33 -39
- package/src/components/PrivacyPolicyMessage/hooks.tsx +49 -0
- package/src/components/PrivacyPolicyMessage/index.tsx +21 -0
- package/src/components/Rate/FeedbackModal.tsx +86 -0
- package/src/components/Rate/hook.tsx +61 -0
- package/src/components/Rate/index.tsx +36 -0
- package/src/components/Rate/on-nps-submit.ts +18 -0
- package/src/components/Rate/show-rate-us-modals.tsx +29 -0
- package/src/components/Rate/utils.ts +11 -0
- package/src/components/Toaster.tsx +82 -3
- package/src/components/TypeForm/hook.tsx +13 -0
- package/src/components/TypeForm/index.tsx +50 -0
- package/src/components/TypeForm/show-typeform-modal.tsx +10 -0
- package/src/components/TypeForm/utils.ts +8 -0
- package/src/components/UserMenu.tsx +32 -8
- package/src/components/error/ErrorBoundary.tsx +11 -2
- package/src/components/error/ErrorManager.ts +22 -6
- package/src/components/error/SilentErrorBoundary.tsx +12 -2
- package/src/components/menu/MenuContent.tsx +102 -110
- package/src/components/menu/MenuSectionGroup.tsx +121 -0
- package/src/components/menu/MenuSections.tsx +342 -93
- package/src/components/menu/PageSelector.tsx +16 -4
- package/src/components/menu/types.ts +221 -9
- package/src/components/tour/StepContainer.tsx +92 -0
- package/src/components/tour/StepNavigation.tsx +72 -0
- package/src/components/tour/StepTitle.tsx +28 -0
- package/src/components/tour/hook.ts +12 -0
- package/src/components/tour/index.ts +6 -0
- package/src/components/tour/manager.tsx +119 -0
- package/src/components/tour/utils.tsx +119 -0
- package/src/components/user-menu-manager.ts +31 -0
- package/src/dictionary.ts +7 -2
- package/src/elements.ts +7 -0
- package/src/index.ts +15 -8
- package/src/layout.css +190 -35
- package/src/svg/StarFillWithGradient.tsx +14 -0
- package/src/toaster.tsx +90 -13
- package/src/types.ts +4 -0
- package/src/utils.ts +9 -142
- package/dist/components/BottomNotification.d.ts +0 -1
- package/dist/components/BottomNotification.d.ts.map +0 -1
- package/dist/components/BottomNotification.js +0 -2
- package/dist/components/BottomNotification.js.map +0 -1
- package/dist/components/BottomPanel.d.ts +0 -1
- package/dist/components/BottomPanel.d.ts.map +0 -1
- package/dist/components/BottomPanel.js +0 -2
- package/dist/components/BottomPanel.js.map +0 -1
- package/dist/components/SelectionList.d.ts +0 -36
- package/dist/components/SelectionList.d.ts.map +0 -1
- package/dist/components/SelectionList.js +0 -140
- package/dist/components/SelectionList.js.map +0 -1
- package/dist/components/error/ErrorFeedback.d.ts +0 -3
- package/dist/components/error/ErrorFeedback.d.ts.map +0 -1
- package/dist/components/error/ErrorFeedback.js +0 -66
- package/dist/components/error/ErrorFeedback.js.map +0 -1
- package/dist/components/menu/use-check-text-overflow.d.ts +0 -6
- package/dist/components/menu/use-check-text-overflow.d.ts.map +0 -1
- package/dist/components/menu/use-check-text-overflow.js +0 -20
- package/dist/components/menu/use-check-text-overflow.js.map +0 -1
- package/dist/components/menu/use-keyboard-controls.d.ts +0 -23
- package/dist/components/menu/use-keyboard-controls.d.ts.map +0 -1
- package/dist/components/menu/use-keyboard-controls.js +0 -49
- package/dist/components/menu/use-keyboard-controls.js.map +0 -1
- package/dist/components/tour/PortalSwitcherStep.d.ts +0 -3
- package/dist/components/tour/PortalSwitcherStep.d.ts.map +0 -1
- package/dist/components/tour/PortalSwitcherStep.js +0 -29
- package/dist/components/tour/PortalSwitcherStep.js.map +0 -1
- package/dist/components/types.d.ts +0 -15
- package/dist/components/types.d.ts.map +0 -1
- package/dist/components/types.js.map +0 -1
- package/dist/layout-context.d.ts +0 -10
- package/dist/layout-context.d.ts.map +0 -1
- package/dist/layout-context.js +0 -11
- package/dist/layout-context.js.map +0 -1
- package/dist/svg/AI.d.ts +0 -6
- package/dist/svg/AI.d.ts.map +0 -1
- package/dist/svg/AI.js +0 -9
- package/dist/svg/AI.js.map +0 -1
- package/dist/svg/EDP.d.ts +0 -6
- package/dist/svg/EDP.d.ts.map +0 -1
- package/dist/svg/EDP.js +0 -5
- package/dist/svg/EDP.js.map +0 -1
- package/dist/svg/Forbidden.d.ts +0 -6
- package/dist/svg/Forbidden.d.ts.map +0 -1
- package/dist/svg/Forbidden.js +0 -4
- package/dist/svg/Forbidden.js.map +0 -1
- package/dist/svg/HUB.d.ts +0 -6
- package/dist/svg/HUB.d.ts.map +0 -1
- package/dist/svg/HUB.js +0 -5
- package/dist/svg/HUB.js.map +0 -1
- package/dist/svg/Logo.d.ts +0 -2
- package/dist/svg/Logo.d.ts.map +0 -1
- package/dist/svg/Logo.js +0 -4
- package/dist/svg/Logo.js.map +0 -1
- package/dist/svg/NotFound.d.ts +0 -6
- package/dist/svg/NotFound.d.ts.map +0 -1
- package/dist/svg/NotFound.js +0 -4
- package/dist/svg/NotFound.js.map +0 -1
- package/dist/svg/ServerError.d.ts +0 -6
- package/dist/svg/ServerError.d.ts.map +0 -1
- package/dist/svg/ServerError.js +0 -4
- package/dist/svg/ServerError.js.map +0 -1
- package/dist/svg/Unauthenticated.d.ts +0 -6
- package/dist/svg/Unauthenticated.d.ts.map +0 -1
- package/dist/svg/Unauthenticated.js +0 -4
- package/dist/svg/Unauthenticated.js.map +0 -1
- package/src/components/BottomPanel.tsx +0 -0
- package/src/components/SelectionList.tsx +0 -272
- package/src/components/error/ErrorFeedback.tsx +0 -114
- package/src/components/menu/use-check-text-overflow.tsx +0 -26
- package/src/components/menu/use-keyboard-controls.tsx +0 -70
- package/src/components/tour/PortalSwitcherStep.tsx +0 -36
- package/src/components/types.ts +0 -15
- package/src/layout-context.tsx +0 -22
- package/src/svg/AI.tsx +0 -37
- package/src/svg/EDP.tsx +0 -35
- package/src/svg/Forbidden.tsx +0 -22
- package/src/svg/HUB.tsx +0 -35
- package/src/svg/Logo.tsx +0 -35
- package/src/svg/NotFound.tsx +0 -16
- package/src/svg/ServerError.tsx +0 -33
- package/src/svg/Unauthenticated.tsx +0 -16
- /package/dist/components/{types.js → NotificationCenter/types.js} +0 -0
- /package/src/components/{BottomNotification.tsx → ContactModal.tsx} +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { theme } from '@stack-spot/portal-theme'
|
|
2
|
+
import { styled } from 'styled-components'
|
|
3
|
+
import { Backdrop } from '../Backdrop'
|
|
4
|
+
|
|
5
|
+
export const NotificationBox = styled.div`
|
|
6
|
+
.notification-button {
|
|
7
|
+
border: none;
|
|
8
|
+
background: transparent;
|
|
9
|
+
margin: 0 40px;
|
|
10
|
+
position: relative;
|
|
11
|
+
|
|
12
|
+
&.loading {
|
|
13
|
+
cursor: progress;
|
|
14
|
+
opacity: 0.5;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
&:before {
|
|
18
|
+
content: '';
|
|
19
|
+
position: absolute;
|
|
20
|
+
right: 9px;
|
|
21
|
+
top: 9px;
|
|
22
|
+
width: 12px;
|
|
23
|
+
height: 12px;
|
|
24
|
+
border-radius: 50%;
|
|
25
|
+
background-color: ${theme.color.danger['500']};
|
|
26
|
+
transform: scale(0);
|
|
27
|
+
transition: transform ease-in 0.3s;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&.unread:before {
|
|
31
|
+
transform: scale(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
`
|
|
35
|
+
|
|
36
|
+
export const StyledBackdrop = styled(Backdrop)`
|
|
37
|
+
position: absolute;
|
|
38
|
+
top: calc(var(--header-height) + 10px);
|
|
39
|
+
right: 60px;
|
|
40
|
+
box-shadow: 4px 4px 48px ${theme.color.danger.contrastText};
|
|
41
|
+
|
|
42
|
+
.notification-panel {
|
|
43
|
+
width: 400px;
|
|
44
|
+
padding: 16px;
|
|
45
|
+
border-radius: 4px;
|
|
46
|
+
background-color: ${theme.color.light[300]};
|
|
47
|
+
border: 1px solid ${theme.color.light[400]};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.filter-list {
|
|
51
|
+
list-style: none;
|
|
52
|
+
margin: 16px 0;
|
|
53
|
+
padding: 0;
|
|
54
|
+
display: flex;
|
|
55
|
+
flex-direction: row;
|
|
56
|
+
justify-content: space-between;
|
|
57
|
+
.filter-btn {
|
|
58
|
+
&:focus {
|
|
59
|
+
border-color: transparent;
|
|
60
|
+
}
|
|
61
|
+
&[aria-pressed="true"] {
|
|
62
|
+
border-color: ${theme.color.primary[500]};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.see-all {
|
|
68
|
+
margin-top: 8px;
|
|
69
|
+
width: 100%;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.error-feedback {
|
|
73
|
+
flex-direction: column;
|
|
74
|
+
}
|
|
75
|
+
`
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { NotificationListProps } from '@stack-spot/portal-components/Notifications'
|
|
2
|
+
|
|
3
|
+
export type NotificationFilter = 'ALL' | 'UNREAD' | 'HIGH' | 'MEDIUM' | 'LOW'
|
|
4
|
+
|
|
5
|
+
export interface NotificationPanelProps extends Omit<NotificationListProps, 'compact' | 'onCommit' | 'onUncommit'> {
|
|
6
|
+
filter: NotificationFilter,
|
|
7
|
+
loading: boolean,
|
|
8
|
+
error: any,
|
|
9
|
+
onFilter: (filter: NotificationFilter) => Promise<void>,
|
|
10
|
+
visible: boolean,
|
|
11
|
+
onClose: () => void,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface NotificationPanelHeaderProps {
|
|
15
|
+
filter: NotificationFilter,
|
|
16
|
+
onChangeFilter: (value: NotificationFilter) => Promise<void>,
|
|
17
|
+
onClose: () => void,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface FilterButtonProps {
|
|
21
|
+
value: NotificationFilter,
|
|
22
|
+
current: NotificationFilter,
|
|
23
|
+
onChangeFilter: (value: NotificationFilter) => void,
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { LoadNotificationsFilters } from '@stack-spot/portal-components/Notifications'
|
|
2
|
+
import { NotificationFilter } from './types'
|
|
3
|
+
|
|
4
|
+
const empty: LoadNotificationsFilters = { committed: undefined, context: undefined, criticality: undefined, search: undefined }
|
|
5
|
+
|
|
6
|
+
export function getFiltersFromName(filterName: NotificationFilter): LoadNotificationsFilters {
|
|
7
|
+
switch (filterName) {
|
|
8
|
+
case 'ALL': return empty
|
|
9
|
+
case 'HIGH': return { ...empty, criticality: 'HIGH' }
|
|
10
|
+
case 'LOW': return { ...empty, criticality: 'LOW' }
|
|
11
|
+
case 'MEDIUM': return { ...empty, criticality: 'MEDIUM' }
|
|
12
|
+
case 'UNREAD': return { ...empty, committed: false }
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getNameFromFilters(filters: LoadNotificationsFilters): NotificationFilter {
|
|
17
|
+
if (filters.committed === false) return 'UNREAD'
|
|
18
|
+
if (filters.criticality) return filters.criticality
|
|
19
|
+
return 'ALL'
|
|
20
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Flex, Text } from '@citric/core'
|
|
2
|
-
import { TimesMini } from '@citric/icons'
|
|
2
|
+
import { ArrowLeft, TimesMini } from '@citric/icons'
|
|
3
3
|
import { IconButton } from '@citric/ui'
|
|
4
4
|
import { WithStyle, listToClass, theme } from '@stack-spot/portal-theme'
|
|
5
5
|
import { ReactNode } from 'react'
|
|
@@ -9,14 +9,36 @@ import { useDictionary } from '../dictionary'
|
|
|
9
9
|
export const CLOSE_OVERLAY_ID = 'close-overlay'
|
|
10
10
|
|
|
11
11
|
export interface OverlayContentProps extends WithStyle {
|
|
12
|
+
/**
|
|
13
|
+
* The title for the modal or right panel.
|
|
14
|
+
*/
|
|
12
15
|
title: string,
|
|
16
|
+
/**
|
|
17
|
+
* The subtitle for the modal or right panel.
|
|
18
|
+
*/
|
|
13
19
|
subtitle?: string,
|
|
20
|
+
/**
|
|
21
|
+
* Function to call when the "go back" button is pressed. If unset, the button is not shown.
|
|
22
|
+
*/
|
|
23
|
+
onGoBack?: () => void,
|
|
24
|
+
/**
|
|
25
|
+
* The content for the modal or right panel.
|
|
26
|
+
*/
|
|
14
27
|
children: ReactNode,
|
|
28
|
+
/**
|
|
29
|
+
* A function to run when the close button is pressed.
|
|
30
|
+
*/
|
|
15
31
|
onClose?: () => void,
|
|
16
32
|
}
|
|
17
33
|
|
|
18
34
|
interface Props extends OverlayContentProps {
|
|
35
|
+
/**
|
|
36
|
+
* A function to run when the close button is pressed.
|
|
37
|
+
*/
|
|
19
38
|
onClose: () => void,
|
|
39
|
+
/**
|
|
40
|
+
* Whether this is a modal or a right panel.
|
|
41
|
+
*/
|
|
20
42
|
type: 'modal' | 'panel',
|
|
21
43
|
}
|
|
22
44
|
|
|
@@ -34,23 +56,36 @@ const ContentBox = styled.section`
|
|
|
34
56
|
flex-direction: column;
|
|
35
57
|
flex: 1;
|
|
36
58
|
}
|
|
37
|
-
header {
|
|
59
|
+
> header {
|
|
38
60
|
display: flex;
|
|
39
61
|
flex-direction: row;
|
|
40
62
|
margin-bottom: 1.25rem;
|
|
41
63
|
}
|
|
42
64
|
`
|
|
43
65
|
|
|
44
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Renders a modal or right panel with title, subtitle, close button and content.
|
|
68
|
+
* @param props the React props for the component {@link Props}.
|
|
69
|
+
*/
|
|
70
|
+
export const OverlayContent = ({ children, title, subtitle, className, style, onClose, onGoBack, type }: Props) => {
|
|
45
71
|
const t = useDictionary()
|
|
46
72
|
return (
|
|
47
73
|
<ContentBox style={style} className={listToClass([className, type])}>
|
|
48
74
|
<header>
|
|
49
75
|
<Flex flexDirection="column" flex={1}>
|
|
50
|
-
<
|
|
76
|
+
<Flex style={{ gap: '6px' }}>
|
|
77
|
+
{onGoBack && (
|
|
78
|
+
<IconButton appearance="circle" onClick={onGoBack} title={t.goBack} aria-label={t.goBack}>
|
|
79
|
+
<ArrowLeft />
|
|
80
|
+
</IconButton>
|
|
81
|
+
)}
|
|
82
|
+
<Text as="h1" appearance={type === 'modal' ? 'h3' : 'h4'}>{title}</Text>
|
|
83
|
+
</Flex>
|
|
51
84
|
{subtitle && <Text appearance="body2" colorScheme="light.700">{subtitle}</Text>}
|
|
52
85
|
</Flex>
|
|
53
|
-
<IconButton onClick={onClose} title={t.close} aria-label={t.close} id={CLOSE_OVERLAY_ID}
|
|
86
|
+
<IconButton appearance="circle" onClick={onClose} title={t.close} aria-label={t.close} id={CLOSE_OVERLAY_ID}>
|
|
87
|
+
<TimesMini />
|
|
88
|
+
</IconButton>
|
|
54
89
|
</header>
|
|
55
90
|
{children}
|
|
56
91
|
</ContentBox>
|
|
@@ -1,26 +1,39 @@
|
|
|
1
|
-
import { Button, Flex, IconBox
|
|
1
|
+
import { Button, Flex, IconBox } from '@citric/core'
|
|
2
2
|
import { ArrowRight, CheckCircleFill, Select } from '@citric/icons'
|
|
3
|
+
import { SelectionList } from '@stack-spot/portal-components/SelectionList'
|
|
4
|
+
import { AI, CS, EDP, HUB, Logo } from '@stack-spot/portal-components/svg'
|
|
3
5
|
import { theme } from '@stack-spot/portal-theme'
|
|
4
|
-
import { useTranslate } from '@stack-spot/portal-translate'
|
|
5
6
|
import { ReactNode, useState } from 'react'
|
|
6
7
|
import styled from 'styled-components'
|
|
7
|
-
import {
|
|
8
|
-
import { AI } from '../svg/AI'
|
|
9
|
-
import { EDP } from '../svg/EDP'
|
|
10
|
-
import { HUB } from '../svg/HUB'
|
|
11
|
-
import { Logo } from '../svg/Logo'
|
|
12
|
-
import { PortalAcronym } from './types'
|
|
13
|
-
|
|
8
|
+
import { PortalAcronym } from '../types'
|
|
14
9
|
|
|
15
10
|
const Logos: Record<PortalAcronym, ReactNode> = {
|
|
16
11
|
'AI': <AI />,
|
|
17
12
|
'EDP': <EDP />,
|
|
18
13
|
'HUB': <HUB />,
|
|
14
|
+
'CS': <CS />,
|
|
15
|
+
'ACCOUNT': <Logo />,
|
|
19
16
|
}
|
|
20
17
|
|
|
21
|
-
export interface Portal {
|
|
18
|
+
export interface Portal {
|
|
19
|
+
/**
|
|
20
|
+
* A Stackspot Portal.
|
|
21
|
+
*/
|
|
22
|
+
acronym: PortalAcronym,
|
|
23
|
+
/**
|
|
24
|
+
* The URL to the Stackspot Portal.
|
|
25
|
+
*/
|
|
26
|
+
url: string,
|
|
27
|
+
/**
|
|
28
|
+
* Show portal on List
|
|
29
|
+
*/
|
|
30
|
+
showOnList?: boolean,
|
|
31
|
+
}
|
|
22
32
|
|
|
23
33
|
export interface PortalSwitcherProps {
|
|
34
|
+
/**
|
|
35
|
+
* The Stackspot portals to show in the selector.
|
|
36
|
+
*/
|
|
24
37
|
portals?: Portal[],
|
|
25
38
|
}
|
|
26
39
|
|
|
@@ -57,7 +70,6 @@ const PortalSwitcherBox = styled(Flex)`
|
|
|
57
70
|
}
|
|
58
71
|
|
|
59
72
|
.action {
|
|
60
|
-
padding: 16px;
|
|
61
73
|
background-color: ${theme.color.light['400']};
|
|
62
74
|
border-width: 1px;
|
|
63
75
|
border-style: solid;
|
|
@@ -69,6 +81,7 @@ const PortalSwitcherBox = styled(Flex)`
|
|
|
69
81
|
}
|
|
70
82
|
|
|
71
83
|
a {
|
|
84
|
+
padding: 16px;
|
|
72
85
|
height: auto;
|
|
73
86
|
transition: unset;
|
|
74
87
|
align-items: flex-start;
|
|
@@ -80,9 +93,13 @@ const PortalSwitcherBox = styled(Flex)`
|
|
|
80
93
|
`
|
|
81
94
|
const PORTAL_SWITCHER_ID = 'PortalSwitcher'
|
|
82
95
|
|
|
96
|
+
/**
|
|
97
|
+
* A selector with different Stackspot portals.
|
|
98
|
+
* Each item contains a logo with a link to the portal.
|
|
99
|
+
* @param props the component Props {@link PortalSwitcherProps}.
|
|
100
|
+
*/
|
|
83
101
|
export const PortalSwitcher = ({ portals = [] }: PortalSwitcherProps) => {
|
|
84
102
|
const [visible, setVisible] = useState<boolean>(false)
|
|
85
|
-
const t = useTranslate(translations)
|
|
86
103
|
const currentPortal = portals?.find(portal => location.href.startsWith(portal.url))
|
|
87
104
|
|
|
88
105
|
return <PortalSwitcherBox>
|
|
@@ -93,10 +110,8 @@ export const PortalSwitcher = ({ portals = [] }: PortalSwitcherProps) => {
|
|
|
93
110
|
colorScheme="light"
|
|
94
111
|
aria-controls={PORTAL_SWITCHER_ID}
|
|
95
112
|
aria-expanded={visible}
|
|
96
|
-
aria-label={`${t.portalSwitcher}: ${currentPortal?.acronym} ${t.selected}`}
|
|
97
113
|
onClick={() => {
|
|
98
|
-
setVisible(
|
|
99
|
-
announce(`${t.portalSwitcher} ${t.selected}`)
|
|
114
|
+
setVisible(!visible)
|
|
100
115
|
}}>
|
|
101
116
|
<Flex alignItems="center" className="portal-switcher">
|
|
102
117
|
{Logos[currentPortal.acronym]}
|
|
@@ -108,18 +123,15 @@ export const PortalSwitcher = ({ portals = [] }: PortalSwitcherProps) => {
|
|
|
108
123
|
<Logo />}
|
|
109
124
|
<SelectionList
|
|
110
125
|
id={PORTAL_SWITCHER_ID}
|
|
111
|
-
items={portals?.map(portal => ({
|
|
126
|
+
items={portals?.filter((portal) => portal.showOnList !== false).map(portal => ({
|
|
112
127
|
label: {
|
|
113
128
|
id: portal.acronym,
|
|
114
|
-
element: <Flex
|
|
115
|
-
{Logos[portal.acronym]}
|
|
116
|
-
<Text appearance="microtext1" mt={3} colorScheme="light.700">{t[portal.acronym]}</Text>
|
|
117
|
-
</Flex>,
|
|
129
|
+
element: <Flex w="250px">{Logos[portal.acronym]}</Flex>,
|
|
118
130
|
},
|
|
119
131
|
target: '_self',
|
|
120
132
|
href: portal.url,
|
|
121
133
|
active: currentPortal?.acronym == portal.acronym,
|
|
122
|
-
iconActive: <CheckCircleFill
|
|
134
|
+
iconActive: <CheckCircleFill />,
|
|
123
135
|
iconRight: portal.acronym !== currentPortal?.acronym ? <ArrowRight /> : undefined,
|
|
124
136
|
}))}
|
|
125
137
|
visible={visible}
|
|
@@ -127,21 +139,3 @@ export const PortalSwitcher = ({ portals = [] }: PortalSwitcherProps) => {
|
|
|
127
139
|
onHide={() => setVisible(false)} />
|
|
128
140
|
</PortalSwitcherBox >
|
|
129
141
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const translations = {
|
|
133
|
-
en: {
|
|
134
|
-
EDP: 'Efficient and secure solutions from code to production deployment.',
|
|
135
|
-
AI: 'Speed up coding with efficient suggestions and high-quality results.',
|
|
136
|
-
HUB: 'Discover AI Stacks, knowledge sources, and quick commands, all in one streamlined hub.',
|
|
137
|
-
portalSwitcher: 'Portal switcher',
|
|
138
|
-
selected: 'selected',
|
|
139
|
-
},
|
|
140
|
-
pt: {
|
|
141
|
-
EDP: 'Soluções eficientes e seguras do código até a implantação em produção.',
|
|
142
|
-
AI: 'Acelere o desenvolvimento com sugestões eficientes e resultados de alta qualidade.',
|
|
143
|
-
HUB: 'Descubra AI Stacks, knownledge sources e quick commands, tudo em um hub simplificado.',
|
|
144
|
-
portalSwitcher: 'Seletor de portais',
|
|
145
|
-
selected: 'selecionado',
|
|
146
|
-
},
|
|
147
|
-
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
2
|
+
import { useEffect, useState } from 'react'
|
|
3
|
+
import { overlay } from '../../LayoutOverlayManager'
|
|
4
|
+
import { PrivacyPolicyMessage, PrivacyPolicyMessageProps } from '.'
|
|
5
|
+
|
|
6
|
+
interface PrivacyPolicyProps extends PrivacyPolicyMessageProps {
|
|
7
|
+
policy?: string,
|
|
8
|
+
policyValue?: string,
|
|
9
|
+
domain?: string,
|
|
10
|
+
confirmText?: string,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function usePrivacyPolicyEffect({
|
|
14
|
+
policy = 'okCookies',
|
|
15
|
+
policyValue = 'true',
|
|
16
|
+
domain = '.stackspot.com',
|
|
17
|
+
privacyPoliceUrl,
|
|
18
|
+
message,
|
|
19
|
+
policyText,
|
|
20
|
+
confirmText,
|
|
21
|
+
}: PrivacyPolicyProps) {
|
|
22
|
+
const t = useTranslate(dictionary)
|
|
23
|
+
const [visible, setVisible] = useState(!document.cookie.match(new RegExp(`${policy}=([^;]+)`))?.[1])
|
|
24
|
+
|
|
25
|
+
async function checkPolicy() {
|
|
26
|
+
if (visible) {
|
|
27
|
+
await overlay.showBottomDialog({
|
|
28
|
+
confirm: confirmText || t.ok,
|
|
29
|
+
children: <PrivacyPolicyMessage privacyPoliceUrl={privacyPoliceUrl} message={message} policyText={policyText} />,
|
|
30
|
+
})
|
|
31
|
+
document.cookie = `${policy}=${policyValue};path=/${location.host.endsWith(domain) ? `;domain=${domain}` : ''}`
|
|
32
|
+
setVisible(false)
|
|
33
|
+
}
|
|
34
|
+
else overlay.closeBottomDialog()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
checkPolicy()
|
|
39
|
+
}, [visible])
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const dictionary = {
|
|
43
|
+
en: {
|
|
44
|
+
ok: 'Ok',
|
|
45
|
+
},
|
|
46
|
+
pt: {
|
|
47
|
+
ok: 'Ok',
|
|
48
|
+
},
|
|
49
|
+
} satisfies Dictionary
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IconBox, Link, Text } from '@citric/core'
|
|
2
|
+
import { Cookie } from '@citric/icons'
|
|
3
|
+
|
|
4
|
+
export interface PrivacyPolicyMessageProps {
|
|
5
|
+
message: string,
|
|
6
|
+
policyText?: string,
|
|
7
|
+
privacyPoliceUrl?: string,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const PrivacyPolicyMessage = ({ message, policyText, privacyPoliceUrl }: PrivacyPolicyMessageProps) => <>
|
|
11
|
+
<IconBox size="md" colorIcon="inverse">
|
|
12
|
+
<Cookie />
|
|
13
|
+
</IconBox>
|
|
14
|
+
<Text>
|
|
15
|
+
{message}
|
|
16
|
+
{privacyPoliceUrl && <Link colorScheme="inverse.contrastText" weight="bold" href={privacyPoliceUrl} target="_blank">
|
|
17
|
+
{policyText}
|
|
18
|
+
</Link>}
|
|
19
|
+
</Text>
|
|
20
|
+
</>
|
|
21
|
+
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Box, Button, Flex, IconBox, Styles, Text } from '@citric/core'
|
|
2
|
+
import { ArrowRight, TimesMini } from '@citric/icons'
|
|
3
|
+
import { IconButton } from '@citric/ui'
|
|
4
|
+
import { theme } from '@stack-spot/portal-theme'
|
|
5
|
+
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
6
|
+
import { useCallback, useEffect, useState } from 'react'
|
|
7
|
+
import { shouldShowNpsModal } from './hook'
|
|
8
|
+
import { checkVisibility } from './utils'
|
|
9
|
+
|
|
10
|
+
const style: Styles = {
|
|
11
|
+
box: {
|
|
12
|
+
width: '438px',
|
|
13
|
+
bg: 'light.500',
|
|
14
|
+
position: 'absolute',
|
|
15
|
+
top: 0,
|
|
16
|
+
right: 0,
|
|
17
|
+
p: 5,
|
|
18
|
+
zIndex: 1,
|
|
19
|
+
borderRadius: '16px',
|
|
20
|
+
boxShadow: `4px 4px 48px 0px ${theme.color.light[300]}`,
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface Props {
|
|
25
|
+
onClick: () => void,
|
|
26
|
+
portal: 'EDP' | 'AI',
|
|
27
|
+
customShouldShowNpsModal?: () => boolean,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const FeedbackModal = ({ onClick, portal, customShouldShowNpsModal }: Props) => {
|
|
31
|
+
const t = useTranslate(dictionary)
|
|
32
|
+
const [isNpsVisible, setIsNpsVisible] = useState(customShouldShowNpsModal ? customShouldShowNpsModal() : shouldShowNpsModal())
|
|
33
|
+
|
|
34
|
+
const handleClose = () => {
|
|
35
|
+
localStorage.setItem('RATED_US_IN', Date.now().toString())
|
|
36
|
+
setIsNpsVisible(false)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const visibilityCheck = useCallback((event: StorageEvent) => checkVisibility(event, setIsNpsVisible, customShouldShowNpsModal), [])
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
checkVisibility({ key: 'RATED_US_IN' } as StorageEvent, setIsNpsVisible, customShouldShowNpsModal)
|
|
43
|
+
|
|
44
|
+
window.addEventListener('storage', visibilityCheck)
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
window.removeEventListener('storage', visibilityCheck)
|
|
48
|
+
}
|
|
49
|
+
}, [])
|
|
50
|
+
|
|
51
|
+
return isNpsVisible ? (
|
|
52
|
+
<Box sx={style.box} id="feedback-modal">
|
|
53
|
+
<Flex justifyContent="space-between" flexWrap="nowrap">
|
|
54
|
+
<Text appearance="h5" mb={6}>{t.title}{portal}?</Text>
|
|
55
|
+
<IconButton onClick={handleClose} id="feedback-modal-close-icon">
|
|
56
|
+
<TimesMini />
|
|
57
|
+
</IconButton>
|
|
58
|
+
</Flex>
|
|
59
|
+
<Text sx={{ lineHeight: '24px' }}>
|
|
60
|
+
{t.description}
|
|
61
|
+
</Text>
|
|
62
|
+
<Flex flexDirection="row-reverse" mt={7} mb={4}>
|
|
63
|
+
<Button onClick={onClick} size="md">
|
|
64
|
+
{t.buttonText}
|
|
65
|
+
<IconBox colorIcon="inverse.contrastText" ml={2}>
|
|
66
|
+
<ArrowRight />
|
|
67
|
+
</IconBox>
|
|
68
|
+
</Button>
|
|
69
|
+
</Flex>
|
|
70
|
+
</Box>
|
|
71
|
+
) : null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const dictionary = {
|
|
75
|
+
en: {
|
|
76
|
+
title: 'How’s your experience with StackSpot ',
|
|
77
|
+
description: 'Your feedback helps us make the platform more useful and intuitive for you. It only takes a few minutes.',
|
|
78
|
+
buttonText: 'Share your feedback',
|
|
79
|
+
},
|
|
80
|
+
pt: {
|
|
81
|
+
title: 'Como está sua experiência com StackSpot ',
|
|
82
|
+
description: 'Seu feedback nos ajuda a tornar a plataforma mais útil e intuitiva para você. Leva apenas alguns minutos.',
|
|
83
|
+
buttonText: 'Compartilhe seu feedback',
|
|
84
|
+
},
|
|
85
|
+
} satisfies Dictionary
|
|
86
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
|
|
2
|
+
// Function to check if the difference between two dates is greater than 30 days
|
|
3
|
+
export function isLessThan30Days(date1: Date, date2: Date) {
|
|
4
|
+
// Get the timestamps of the dates
|
|
5
|
+
const timestamp1 = date1.getTime()
|
|
6
|
+
const timestamp2 = date2.getTime()
|
|
7
|
+
|
|
8
|
+
// Calculate the difference in milliseconds
|
|
9
|
+
const differenceInMilliseconds = Math.abs(timestamp2 - timestamp1)
|
|
10
|
+
|
|
11
|
+
// Convert milliseconds to days
|
|
12
|
+
const differenceInDays = differenceInMilliseconds / (1000 * 60 * 60 * 24)
|
|
13
|
+
|
|
14
|
+
// Check if the difference is fewer than 30 days
|
|
15
|
+
return differenceInDays < 30
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Function to check if a day is business day
|
|
19
|
+
const isBusinessDay = (date: Date): boolean => {
|
|
20
|
+
const dayOfWeek = date.getDay()
|
|
21
|
+
return dayOfWeek !== 0 && dayOfWeek !== 6 // 0 = sunday, 6 = saturday
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Function that returns a boolean to show modal feedback
|
|
25
|
+
export const shouldShowNpsModal = (): boolean => {
|
|
26
|
+
const today = new Date()
|
|
27
|
+
const currentDay = today.getDate()
|
|
28
|
+
|
|
29
|
+
// Check if the month has already been evaluated
|
|
30
|
+
const ratedInfo = localStorage.getItem('RATED_US_IN')
|
|
31
|
+
|
|
32
|
+
if (ratedInfo) {
|
|
33
|
+
const savedDate = new Date(parseInt(ratedInfo, 10))
|
|
34
|
+
const isSameMonth = savedDate.getMonth() === today.getMonth() && savedDate.getFullYear() === today.getFullYear()
|
|
35
|
+
|
|
36
|
+
// If it has already been evaluated this month, do not show the modal
|
|
37
|
+
if (isSameMonth) return false
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Variables to control working days shown and extension day
|
|
41
|
+
let businessDaysShown = 0
|
|
42
|
+
let day = 25
|
|
43
|
+
|
|
44
|
+
// Iterate from the 25th until you can show 3 business days
|
|
45
|
+
while (businessDaysShown < 3) {
|
|
46
|
+
const checkDate = new Date(today.getFullYear(), today.getMonth(), day)
|
|
47
|
+
|
|
48
|
+
if (isBusinessDay(checkDate)) {
|
|
49
|
+
businessDaysShown++
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// If we are on the current day and have not yet completed the working days, show the modal
|
|
53
|
+
if (currentDay === day) {
|
|
54
|
+
return true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
day++
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Box, Flex } from '@citric/core'
|
|
2
|
+
import { LoadingCircular } from '@citric/ui'
|
|
3
|
+
import { useEffect, useState } from 'react'
|
|
4
|
+
import './on-nps-submit'
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
tfLive: string,
|
|
8
|
+
userId: string,
|
|
9
|
+
orgId: string,
|
|
10
|
+
portal: 'AI' | 'EDP',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const RateComponent = ({ tfLive, userId, orgId, portal }: Props) => {
|
|
14
|
+
const [isLoading, setIsLoading] = useState(true)
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
(window as any).tf?.load()
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
setIsLoading(false)
|
|
20
|
+
}, 2000)
|
|
21
|
+
}, [])
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Box sx={{ minWidth: '650px', minHeight: '500px' }}>
|
|
25
|
+
{isLoading && <Flex alignItems="center" justifyContent="center" w="12" sx={{ height: '100%' }}>
|
|
26
|
+
<LoadingCircular />
|
|
27
|
+
</Flex>}
|
|
28
|
+
<Box sx={{ opacity: isLoading ? '0' : 1 }}>
|
|
29
|
+
<div data-tf-live={tfLive}
|
|
30
|
+
data-tf-hidden={`user_id=${userId},org_id=${orgId},portal_name=${portal}`}
|
|
31
|
+
data-tf-open="time" data-tf-open-value="100" data-tf-on-submit="onNpsSubmit" />
|
|
32
|
+
</Box>
|
|
33
|
+
</Box>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { overlay } from '../../LayoutOverlayManager'
|
|
2
|
+
|
|
3
|
+
function onNpsSubmit(): void {
|
|
4
|
+
localStorage.setItem('RATED_US_IN', Date.now().toString())
|
|
5
|
+
overlay.closeModal()
|
|
6
|
+
document.getElementById('feedback-modal-close-icon')?.click()
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export {}
|
|
10
|
+
|
|
11
|
+
// Attach the function to the window object
|
|
12
|
+
declare global {
|
|
13
|
+
interface Window {
|
|
14
|
+
onNpsSubmit: () => void,
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
window.onNpsSubmit = onNpsSubmit
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { overlay } from '../../LayoutOverlayManager'
|
|
2
|
+
import { FeedbackModal } from './FeedbackModal'
|
|
3
|
+
import { RateComponent } from '.'
|
|
4
|
+
|
|
5
|
+
interface PropsShowFeedbackModal {
|
|
6
|
+
onClick: () => void,
|
|
7
|
+
portal: 'EDP' | 'AI',
|
|
8
|
+
customShouldShowNpsModal?: () => boolean,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const ShowFeedbackModal = ({ onClick, portal, customShouldShowNpsModal }: PropsShowFeedbackModal) => (
|
|
12
|
+
<FeedbackModal onClick={onClick} portal={portal} customShouldShowNpsModal={customShouldShowNpsModal} />
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
interface Props {
|
|
16
|
+
sub: string,
|
|
17
|
+
tenant: string,
|
|
18
|
+
portal: 'EDP' | 'AI',
|
|
19
|
+
formIdentifier: string,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const showRateUsModal = ({ title, ...props }: Props & { title: string }) => {
|
|
23
|
+
const { formIdentifier, sub, tenant, portal } = props
|
|
24
|
+
overlay.showModal({
|
|
25
|
+
title: title,
|
|
26
|
+
children: <RateComponent tfLive={formIdentifier} userId={sub} orgId={tenant} portal={portal} />,
|
|
27
|
+
size: 'large',
|
|
28
|
+
})
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { shouldShowNpsModal } from './hook'
|
|
2
|
+
|
|
3
|
+
export const checkVisibility = (event: StorageEvent, fnUpdateState: React.Dispatch<React.SetStateAction<boolean>>,
|
|
4
|
+
customShouldShow?: () => boolean) => {
|
|
5
|
+
if (event.key === 'RATED_US_IN') {
|
|
6
|
+
const shouldShow = customShouldShow ? customShouldShow() : shouldShowNpsModal()
|
|
7
|
+
if (!shouldShow) {
|
|
8
|
+
fnUpdateState(false)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|