diff --git a/.env.development b/.env.development index b13e9d27d..8c0c17748 100644 --- a/.env.development +++ b/.env.development @@ -2,7 +2,7 @@ REACT_APP_GTM_ID=GTM-WVXPS94 REACT_APP_GTM_AUTH=HjeAxSQB9e685mi-_8YiDw REACT_APP_GTM_ENV=env-4 REACT_APP_API_URL=/api -REACT_APP_TRYBER_WP_API_URL=https://dev.tryber.me/wp-json/appq/v1 +REACT_APP_TRYBER_URL=https://dev.tryber.me REACT_ZAPIER_WEBHOOK=https://hooks.zapier.com/hooks/catch/5196925/bkxm1k6/ REACT_APP_STRAPI_URL=https://admin.unguess.io REACT_APP_STRAPI_API_URL=https://admin.unguess.io/api diff --git a/.env.production b/.env.production index 698d7ae4a..0e0256c21 100644 --- a/.env.production +++ b/.env.production @@ -1,6 +1,6 @@ REACT_APP_GTM_ID=GTM-WVXPS94 REACT_APP_API_URL=/api -REACT_APP_TRYBER_WP_API_URL=https://tryber.me/wp-json/appq/v1 +REACT_APP_TRYBER_URL=https://tryber.me REACT_ZAPIER_WEBHOOK=https://hooks.zapier.com/hooks/catch/5196925/bkxm1k6/ REACT_APP_STRAPI_URL=https://admin.unguess.io REACT_APP_STRAPI_API_URL=https://admin.unguess.io/api diff --git a/package.json b/package.json index 98c90d78d..b4ce92e8b 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "i18n-iso-countries": "^7.3.0", "i18next": "^21.6.14", "i18next-browser-languagedetector": "^6.1.3", + "iframe-resizer-react": "^1.1.0", "prosemirror-commands": "^1.5.0", "prosemirror-dropcursor": "^1.6.1", "prosemirror-gapcursor": "^1.3.1", diff --git a/src/app/theme.tsx b/src/app/theme.tsx index a5ef57533..8a6af258c 100644 --- a/src/app/theme.tsx +++ b/src/app/theme.tsx @@ -3,18 +3,19 @@ import { getColor, } from '@appquality/unguess-design-system'; +// todo: check green 600 export const SEVERITY_COLORS: Record = { critical: baseTheme.palette.red[900], high: baseTheme.palette.yellow[600], medium: baseTheme.palette.blue[600], - low: baseTheme.palette.teal[700], + low: baseTheme.palette.green[600], }; export const SEVERITY_HUES: Record = { critical: baseTheme.palette.red[900], high: baseTheme.palette.yellow[600], medium: baseTheme.palette.blue[600], - low: baseTheme.palette.teal[700], + low: baseTheme.palette.green[600], }; // temporary fix for the bug state colors export const BUG_STATE_COLORS: Record< diff --git a/src/assets/icons/logo.svg b/src/assets/icons/logo.svg new file mode 100644 index 000000000..5a01a2bc8 --- /dev/null +++ b/src/assets/icons/logo.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/common/GoogleTagManager.tsx b/src/common/GoogleTagManager.tsx index e5dfed771..2dd288562 100644 --- a/src/common/GoogleTagManager.tsx +++ b/src/common/GoogleTagManager.tsx @@ -2,6 +2,7 @@ import React, { useEffect } from 'react'; import TagManager, { TagManagerArgs } from 'react-gtm-module'; import { Helmet } from 'react-helmet'; import { useAppSelector } from 'src/app/hooks'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; const tagManagerArgs: TagManagerArgs = { gtmId: process.env.REACT_APP_GTM_ID || 'GTM-WVXPS94', @@ -27,7 +28,7 @@ export const GoogleTagManager = ({ children: React.ReactNode; }) => { const { userData } = useAppSelector((state) => state.user); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const helmet = () => ( diff --git a/src/common/Pages.tsx b/src/common/Pages.tsx index 4d01c15f7..236e85b2d 100644 --- a/src/common/Pages.tsx +++ b/src/common/Pages.tsx @@ -1,21 +1,22 @@ +import { useTranslation } from 'react-i18next'; import { - createBrowserRouter, - createRoutesFromElements, + Navigate, Route, RouterProvider, - Navigate, + createBrowserRouter, + createRoutesFromElements, } from 'react-router-dom'; -import LoginPage from 'src/pages/LoginPage'; +import ErrorBoundaryPage from 'src/common/components/ErrorBoundary/ErrorBoundaryPage'; +import Bug from 'src/pages/Bug'; +import BugForm from 'src/pages/Bugform'; +import Bugs from 'src/pages/Bugs'; +import Campaign from 'src/pages/Campaign'; import Dashboard from 'src/pages/Dashboard'; import Project from 'src/pages/Dashboard/Project'; +import LoginPage from 'src/pages/LoginPage'; import NotFound from 'src/pages/NotFound'; -import Catalog from 'src/pages/Services'; import Service from 'src/pages/Service'; -import Campaign from 'src/pages/Campaign'; -import Bugs from 'src/pages/Bugs'; -import { useTranslation } from 'react-i18next'; -import Bug from 'src/pages/Bug'; -import ErrorBoundaryPage from 'src/common/components/ErrorBoundary/ErrorBoundaryPage'; +import Catalog from 'src/pages/Services'; import { Redirect } from './Redirect'; const Pages = () => { @@ -38,6 +39,11 @@ const Pages = () => { path={`/${langPrefix}/campaigns/:campaignId`} element={} /> + } + /> + } /> { const requestHeaders: HeadersInit = new Headers(); requestHeaders.set('Content-Type', 'application/json'); - const url = `${process.env.REACT_APP_TRYBER_WP_API_URL}/regenerate-campaign-pages/${campaignId}`; + const url = `${process.env.REACT_APP_TRYBER_URL}/wp-json/appq/v1/regenerate-campaign-pages/${campaignId}`; const res = await fetch(url, { method: 'GET', @@ -52,7 +52,7 @@ export const createTasks = async (campaignId: number) => { const requestHeaders: HeadersInit = new Headers(); requestHeaders.set('Content-Type', 'application/json'); - const url = `${process.env.REACT_APP_TRYBER_WP_API_URL}/regenerate-campaign-tasks/${campaignId}`; + const url = `${process.env.REACT_APP_TRYBER_URL}/wp-json/appq/v1/regenerate-campaign-tasks/${campaignId}`; const res = await fetch(url, { method: 'GET', @@ -69,7 +69,7 @@ export const createCrons = async (campaignId: number) => { const requestHeaders: HeadersInit = new Headers(); requestHeaders.set('Content-Type', 'application/json'); - const url = `${process.env.REACT_APP_TRYBER_WP_API_URL}/regenerate-campaign-crons/${campaignId}`; + const url = `${process.env.REACT_APP_TRYBER_URL}/wp-json/appq/v1/regenerate-campaign-crons/${campaignId}`; const res = await fetch(url, { method: 'GET', @@ -86,7 +86,7 @@ export const createUseCases = async (campaignId: number) => { const requestHeaders: HeadersInit = new Headers(); requestHeaders.set('Content-Type', 'application/json'); - const url = `${process.env.REACT_APP_TRYBER_WP_API_URL}/regenerate-campaign-use-cases/${campaignId}`; + const url = `${process.env.REACT_APP_TRYBER_URL}/wp-json/appq/v1/regenerate-campaign-use-cases/${campaignId}`; const res = await fetch(url, { method: 'GET', diff --git a/src/common/components/inviteUsers/campaignSettings.tsx b/src/common/components/inviteUsers/campaignSettings.tsx index fbd5feb68..07e0bd0b9 100644 --- a/src/common/components/inviteUsers/campaignSettings.tsx +++ b/src/common/components/inviteUsers/campaignSettings.tsx @@ -1,17 +1,23 @@ -import { appTheme } from 'src/app/theme'; import { + Button, Label, + MD, Modal, ModalClose, - Span, - useToast, Notification, - Button, + Span, getColor, - MD, + useToast, } from '@appquality/unguess-design-system'; -import { useAppSelector } from 'src/app/hooks'; +import { FormikHelpers } from 'formik'; +import { useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; +import { useAppSelector } from 'src/app/hooks'; +import { appTheme } from 'src/app/theme'; +import { ReactComponent as CampaignsIcon } from 'src/assets/icons/campaign-icon.svg'; +import { ReactComponent as ProjectsIcon } from 'src/assets/icons/project-icon.svg'; +import { ReactComponent as UsersIcon } from 'src/assets/icons/users-share.svg'; +import { ReactComponent as WorkspacesIcon } from 'src/assets/icons/workspace-icon.svg'; import { useDeleteCampaignsByCidUsersMutation, useGetCampaignsByCidQuery, @@ -20,30 +26,27 @@ import { useGetWorkspacesByWidUsersQuery, usePostCampaignsByCidUsersMutation, } from 'src/features/api'; -import { FormikHelpers } from 'formik'; -import { ReactComponent as UsersIcon } from 'src/assets/icons/users-share.svg'; -import { useState } from 'react'; -import { ReactComponent as CampaignsIcon } from 'src/assets/icons/campaign-icon.svg'; -import { ReactComponent as ProjectsIcon } from 'src/assets/icons/project-icon.svg'; -import { ReactComponent as WorkspacesIcon } from 'src/assets/icons/workspace-icon.svg'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; import { getLocalizedCampaignUrl } from 'src/hooks/useLocalizeDashboardUrl'; import i18n from 'src/i18n'; import { AddNewMemberInput } from './addNewMember'; -import { UserItem } from './userItem'; import { PermissionSettingsFooter } from './modalFooter'; import { FixedBody, FlexContainer, SettingsDivider, StyledAccordion, - UsersLabel, - UsersContainer, StyledAccordionPanel, + UsersContainer, + UsersLabel, } from './styled'; +import { UserItem } from './userItem'; export const CampaignSettings = () => { - const { permissionSettingsTitle, campaignId, activeWorkspace } = - useAppSelector((state) => state.navigation); + const { permissionSettingsTitle, campaignId } = useAppSelector( + (state) => state.navigation + ); + const { activeWorkspace } = useActiveWorkspace(); const [isModalOpen, setIsModalOpen] = useState(false); const { t } = useTranslation(); const { addToast } = useToast(); diff --git a/src/common/components/inviteUsers/projectSettings.tsx b/src/common/components/inviteUsers/projectSettings.tsx index e2b267a29..8ce810e46 100644 --- a/src/common/components/inviteUsers/projectSettings.tsx +++ b/src/common/components/inviteUsers/projectSettings.tsx @@ -1,46 +1,49 @@ -import { appTheme } from 'src/app/theme'; import { + Button, Label, + MD, Modal, ModalClose, - Span, - useToast, Notification, - Button, + Span, getColor, - MD, + useToast, } from '@appquality/unguess-design-system'; -import { useAppSelector } from 'src/app/hooks'; +import { FormikHelpers } from 'formik'; +import { useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; +import { useAppSelector } from 'src/app/hooks'; +import { appTheme } from 'src/app/theme'; +import { ReactComponent as ProjectsIcon } from 'src/assets/icons/project-icon.svg'; +import { ReactComponent as UsersIcon } from 'src/assets/icons/users-share.svg'; +import { ReactComponent as WorkspacesIcon } from 'src/assets/icons/workspace-icon.svg'; import { useDeleteProjectsByPidUsersMutation, useGetProjectsByPidUsersQuery, useGetWorkspacesByWidUsersQuery, usePostProjectsByPidUsersMutation, } from 'src/features/api'; -import { FormikHelpers } from 'formik'; -import { ReactComponent as UsersIcon } from 'src/assets/icons/users-share.svg'; -import { useState } from 'react'; -import { ReactComponent as ProjectsIcon } from 'src/assets/icons/project-icon.svg'; -import { ReactComponent as WorkspacesIcon } from 'src/assets/icons/workspace-icon.svg'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; import { getLocalizedProjectUrl } from 'src/hooks/useLocalizeDashboardUrl'; import i18n from 'src/i18n'; import { AddNewMemberInput } from './addNewMember'; -import { UserItem } from './userItem'; import { PermissionSettingsFooter } from './modalFooter'; import { FixedBody, FlexContainer, SettingsDivider, StyledAccordion, - UsersLabel, - UsersContainer, StyledAccordionPanel, + UsersContainer, + UsersLabel, } from './styled'; +import { UserItem } from './userItem'; export const ProjectSettings = () => { - const { permissionSettingsTitle, projectId, activeWorkspace } = - useAppSelector((state) => state.navigation); + const { permissionSettingsTitle, projectId } = useAppSelector( + (state) => state.navigation + ); + const { activeWorkspace } = useActiveWorkspace(); const [isModalOpen, setIsModalOpen] = useState(false); const { t } = useTranslation(); const { addToast } = useToast(); diff --git a/src/common/components/inviteUsers/workspaceSettings.tsx b/src/common/components/inviteUsers/workspaceSettings.tsx index 7b00271ef..8fa74c1d1 100644 --- a/src/common/components/inviteUsers/workspaceSettings.tsx +++ b/src/common/components/inviteUsers/workspaceSettings.tsx @@ -1,40 +1,40 @@ -import { appTheme } from 'src/app/theme'; import { + Button, Label, + MD, Modal, ModalClose, - Span, - useToast, Notification, - Button, + Span, getColor, - MD, + useToast, } from '@appquality/unguess-design-system'; -import { useAppSelector } from 'src/app/hooks'; +import { FormikHelpers } from 'formik'; +import { useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; +import { appTheme } from 'src/app/theme'; +import { ReactComponent as UsersIcon } from 'src/assets/icons/users-share.svg'; +import { ReactComponent as WorkspacesIcon } from 'src/assets/icons/workspace-icon.svg'; import { useDeleteWorkspacesByWidUsersMutation, useGetWorkspacesByWidUsersQuery, usePostWorkspacesByWidUsersMutation, } from 'src/features/api'; -import { FormikHelpers } from 'formik'; -import { ReactComponent as UsersIcon } from 'src/assets/icons/users-share.svg'; -import { ReactComponent as WorkspacesIcon } from 'src/assets/icons/workspace-icon.svg'; -import { useState } from 'react'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; import i18n from 'src/i18n'; import { AddNewMemberInput } from './addNewMember'; -import { UserItem } from './userItem'; import { PermissionSettingsFooter } from './modalFooter'; import { FixedBody, FlexContainer, SettingsDivider, - UsersLabel, UsersContainer, + UsersLabel, } from './styled'; +import { UserItem } from './userItem'; export const WorkspaceSettings = () => { - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const [isModalOpen, setIsModalOpen] = useState(false); const { t } = useTranslation(); const { addToast } = useToast(); diff --git a/src/common/components/navigation/header/MobileToggle.tsx b/src/common/components/navigation/header/MobileToggle.tsx new file mode 100644 index 000000000..40d89cd25 --- /dev/null +++ b/src/common/components/navigation/header/MobileToggle.tsx @@ -0,0 +1,51 @@ +import { + HeaderItem, + HeaderItemIcon, + HeaderItemText, +} from '@appquality/unguess-design-system'; +import { retrieveComponentStyles } from '@zendeskgarden/react-theming'; +import { useTranslation } from 'react-i18next'; +import { useAppDispatch } from 'src/app/hooks'; +import { ReactComponent as MenuIcon } from 'src/assets/icons/menu-stroke.svg'; +import { toggleSidebar } from 'src/features/navigation/navigationSlice'; +import styled from 'styled-components'; + +export const LogoIconContainer = styled(HeaderItem)` + margin-right: 2px; + border-right: none; + cursor: pointer; + @media (max-width: ${({ theme }) => theme.breakpoints.md}) { + right: 0; + left: 0; + margin-right: auto; + margin-left: auto; + position: absolute; + } +`; + +const MenuItem = styled(HeaderItem)` + ${(props) => retrieveComponentStyles('text.primary', props)}; + @media (min-width: ${({ theme }) => theme.breakpoints.md}) { + display: none; + } +`; + +export const MobileToggle = () => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + + const toggleSidebarState = () => { + dispatch(toggleSidebar()); + }; + + return ( + + + + + + {t('__APP_MOBILE_NAVIGATION_MENU_LABEL MAX:5')} + + + ); +}; diff --git a/src/common/components/navigation/header/brandLogo.tsx b/src/common/components/navigation/header/brandLogo.tsx index 20ec3e423..b6ad69d10 100644 --- a/src/common/components/navigation/header/brandLogo.tsx +++ b/src/common/components/navigation/header/brandLogo.tsx @@ -1,17 +1,11 @@ import { HeaderItem, HeaderItemIcon, - HeaderItemText, Logo, } from '@appquality/unguess-design-system'; -import { useTranslation } from 'react-i18next'; -import { useAppDispatch } from 'src/app/hooks'; -import { toggleSidebar } from 'src/features/navigation/navigationSlice'; -import { retrieveComponentStyles } from '@zendeskgarden/react-theming'; -import { ReactComponent as MenuIcon } from 'src/assets/icons/menu-stroke.svg'; -import styled from 'styled-components'; import { useNavigate } from 'react-router-dom'; -import { WorkspacesDropdown } from '../workspacesDropdown'; +import { ReactComponent as LogoFull } from 'src/assets/icons/logo.svg'; +import styled from 'styled-components'; export const LogoIconContainer = styled(HeaderItem)` margin-right: 2px; @@ -26,44 +20,24 @@ export const LogoIconContainer = styled(HeaderItem)` } `; -const MenuItem = styled(HeaderItem)` - ${(props) => retrieveComponentStyles('text.primary', props)}; - position: absolute; - left: 0; - @media (min-width: ${({ theme }) => theme.breakpoints.md}) { - display: none; - } +const LogoFullComponent = styled(LogoFull)` + cursor: pointer; + height: 32px; `; -export const BrandLogo = () => { - const { t } = useTranslation(); - const dispatch = useAppDispatch(); +export const BrandLogo = ({ size }: { size: 'simple' | 'full' }) => { const navigate = useNavigate(); - const toggleSidebarState = () => { - dispatch(toggleSidebar()); - }; - const handleLogoClick = () => { navigate('/'); // Navigate to the root route }; + if (size === 'full') return ; return ( - <> - - - - - - {t('__APP_MOBILE_NAVIGATION_MENU_LABEL MAX:5')} - - - - - - - - - + + + + + ); }; diff --git a/src/common/components/navigation/header/changelog.tsx b/src/common/components/navigation/header/changelog.tsx index 1400bfc99..699e33206 100644 --- a/src/common/components/navigation/header/changelog.tsx +++ b/src/common/components/navigation/header/changelog.tsx @@ -1,8 +1,8 @@ -import { ReactComponent as ChangelogIcon } from 'src/assets/icons/megaphone-stroke.svg'; +import { HeaderItem } from '@appquality/unguess-design-system'; import HeadwayWidget from '@headwayapp/react-widget'; -import styled from 'styled-components'; import { appTheme } from 'src/app/theme'; -import { HeaderItem } from '@appquality/unguess-design-system'; +import { ReactComponent as ChangelogIcon } from 'src/assets/icons/megaphone-stroke.svg'; +import styled from 'styled-components'; const StyledWidget = styled.div` svg { @@ -14,7 +14,7 @@ const StyledWidget = styled.div` `; export const Changelog = () => ( - + diff --git a/src/common/components/navigation/header/header.tsx b/src/common/components/navigation/header/header.tsx index 4fb6c2aa5..0c4261f6b 100644 --- a/src/common/components/navigation/header/header.tsx +++ b/src/common/components/navigation/header/header.tsx @@ -1,13 +1,28 @@ import { Header as UgHeader } from '@appquality/unguess-design-system'; import { appTheme } from 'src/app/theme'; -import { Changelog } from './changelog'; +import { WorkspacesDropdown } from '../workspacesDropdown'; +import { MobileToggle } from './MobileToggle'; import { BrandLogo } from './brandLogo'; +import { Changelog } from './changelog'; import { ProfileAvatar } from './profileAvatar'; -export const Header = () => ( - - - - +export const Header = ({ + logo = 'simple', + loggedIn = true, +}: { + logo?: 'simple' | 'full'; + loggedIn?: boolean; +}) => ( + + {loggedIn && } + + {loggedIn && } +
+ + {loggedIn && } +
); diff --git a/src/common/components/navigation/sidebar/index.tsx b/src/common/components/navigation/sidebar/index.tsx index 771187d3a..a18936a69 100644 --- a/src/common/components/navigation/sidebar/index.tsx +++ b/src/common/components/navigation/sidebar/index.tsx @@ -10,23 +10,24 @@ import { NavToggle, SM, } from '@appquality/unguess-design-system'; -import { appTheme } from 'src/app/theme'; -import i18n from 'src/i18n'; import { PropsWithChildren, useEffect, useRef } from 'react'; -import styled from 'styled-components'; -import { isMaxMedia } from 'src/common/utils'; import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; import { useAppDispatch, useAppSelector } from 'src/app/hooks'; +import { appTheme } from 'src/app/theme'; +import { isMaxMedia } from 'src/common/utils'; import { useGetWorkspacesByWidProjectsQuery } from 'src/features/api'; import { toggleSidebar } from 'src/features/navigation/navigationSlice'; -import { useNavigate } from 'react-router-dom'; -import { SidebarSkeleton } from './skeleton'; -import { ReactComponent as CampaignsIcon } from './icons/campaigns.svg'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; +import i18n from 'src/i18n'; +import styled from 'styled-components'; +import { WorkspacesDropdown } from '../workspacesDropdown'; import { ReactComponent as CampaignsIconActive } from './icons/campaigns-active.svg'; +import { ReactComponent as CampaignsIcon } from './icons/campaigns.svg'; import { ReactComponent as ProjectsIcon } from './icons/projects.svg'; import { ReactComponent as ServicesIconActive } from './icons/services-active.svg'; import { ReactComponent as ServicesIcon } from './icons/services.svg'; -import { WorkspacesDropdown } from '../workspacesDropdown'; +import { SidebarSkeleton } from './skeleton'; const ScrollingContainer = styled.div` display: flex; @@ -48,9 +49,8 @@ export const AppSidebar = (props: PropsWithChildren) => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const navigate = useNavigate(); - const { isSidebarOpen, activeWorkspace } = useAppSelector( - (state) => state.navigation - ); + const { isSidebarOpen } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const prjRef = useRef(null); diff --git a/src/common/components/navigation/workspacesDropdown/index.tsx b/src/common/components/navigation/workspacesDropdown/index.tsx index 12902f15d..d4c678f6b 100644 --- a/src/common/components/navigation/workspacesDropdown/index.tsx +++ b/src/common/components/navigation/workspacesDropdown/index.tsx @@ -9,22 +9,23 @@ import { Menu, } from '@appquality/unguess-design-system'; import { Field } from '@zendeskgarden/react-dropdowns'; -import { useAppDispatch, useAppSelector } from 'src/app/hooks'; -import { useEffect, useState } from 'react'; -import { Workspace } from 'src/features/api'; -import styled from 'styled-components'; -import { saveWorkspaceToLs } from 'src/features/navigation/cachedStorage'; import { retrieveComponentStyles } from '@zendeskgarden/react-theming'; +import { useEffect, useState } from 'react'; +import TagManager from 'react-gtm-module'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import { useAppDispatch, useAppSelector } from 'src/app/hooks'; +import { appTheme } from 'src/app/theme'; import { ReactComponent as WorkspacesIcon } from 'src/assets/icons/workspace-icon.svg'; import API from 'src/common/api'; +import { Workspace } from 'src/features/api'; +import { saveWorkspaceToLs } from 'src/features/navigation/cachedStorage'; import { setWorkspace } from 'src/features/navigation/navigationSlice'; -import TagManager from 'react-gtm-module'; -import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; -import useDebounce from 'src/hooks/useDebounce'; -import { useNavigate } from 'react-router-dom'; import { selectWorkspaces } from 'src/features/workspaces/selectors'; -import { useTranslation } from 'react-i18next'; -import { appTheme } from 'src/app/theme'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; +import useDebounce from 'src/hooks/useDebounce'; +import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; +import styled from 'styled-components'; import { WorkspaceSettings } from '../../inviteUsers/workspaceSettings'; const StyledEllipsis = styled(Ellipsis)<{ isCompact?: boolean }>` @@ -83,7 +84,7 @@ export const WorkspacesDropdown = () => { const navigate = useNavigate(); const homeRoute = useLocalizeRoute(''); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const { userData: user } = useAppSelector((state) => state.user); const workspaces = useAppSelector(selectWorkspaces); diff --git a/src/common/components/utils/getCustomStatusInfo.tsx b/src/common/components/utils/getCustomStatusInfo.tsx index 355a50474..dbbc13337 100644 --- a/src/common/components/utils/getCustomStatusInfo.tsx +++ b/src/common/components/utils/getCustomStatusInfo.tsx @@ -39,7 +39,7 @@ export const getCustomStatusInfo = ( }; default: return { - text: t('__BUG_CUSTOM_STATUS_TO_DO'), + text: CustomStatus, }; } }; diff --git a/src/common/components/utils/getStatusInfo.tsx b/src/common/components/utils/getStatusInfo.tsx index 6d29cfd41..159dc0311 100644 --- a/src/common/components/utils/getStatusInfo.tsx +++ b/src/common/components/utils/getStatusInfo.tsx @@ -30,7 +30,7 @@ export const getStatusInfo = ( return { icon: , text: t('__CAMPAIGN_STATUS_COMPLETED__'), - color: appTheme.palette.green[800], + color: appTheme.palette.green[600], }; case 'incoming': return { @@ -48,7 +48,7 @@ export const getStatusInfo = ( return { icon: , text: t('__CAMPAIGN_TYPE_EXPERIENTIAL__'), - color: appTheme.palette.green[700], + color: appTheme.palette.teal[700], }; default: return {}; diff --git a/src/features/navigation/Navigation.tsx b/src/features/navigation/Navigation.tsx index d55207b64..61598e694 100644 --- a/src/features/navigation/Navigation.tsx +++ b/src/features/navigation/Navigation.tsx @@ -1,32 +1,26 @@ import { Content, + Notification, ProfileModal, useToast, - Notification, } from '@appquality/unguess-design-system'; +import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import { useParams } from 'react-router-dom'; import { useAppDispatch, useAppSelector } from 'src/app/hooks'; +import { AppSidebar } from 'src/common/components/navigation/sidebar'; +import { isDev } from 'src/common/isDevEnvironment'; +import { prepareGravatar } from 'src/common/utils'; +import WPAPI from 'src/common/wpapi'; import { - toggleSidebar, - setWorkspace, setProfileModalOpen, setSidebarOpen, + toggleSidebar, } from 'src/features/navigation/navigationSlice'; -import { AppSidebar } from 'src/common/components/navigation/sidebar'; -import WPAPI from 'src/common/wpapi'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; import i18n from 'src/i18n'; -import { useParams } from 'react-router-dom'; -import { prepareGravatar } from 'src/common/utils'; -import { useEffect } from 'react'; -import API from 'src/common/api'; -import { isDev } from 'src/common/isDevEnvironment'; -import { getWorkspaceFromLS } from './cachedStorage'; -import { isValidWorkspace } from './utils'; -import { selectWorkspaces } from '../workspaces/selectors'; -import { usePathWithoutLocale } from './usePathWithoutLocale'; import { Header } from '../../common/components/navigation/header/header'; - -const cachedWorkspace = getWorkspaceFromLS(); +import { usePathWithoutLocale } from './usePathWithoutLocale'; export const Navigation = ({ children, @@ -40,8 +34,7 @@ export const Navigation = ({ const pathWithoutLocale = usePathWithoutLocale(); const { userData: user } = useAppSelector((state) => state.user); const { isProfileModalOpen } = useAppSelector((state) => state.navigation); - const workspaces = useAppSelector(selectWorkspaces); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const { addToast } = useToast(); // Set isSidebarOpen to false for specific routes @@ -59,28 +52,6 @@ export const Navigation = ({ } }, [route]); - useEffect(() => { - if (workspaces && !activeWorkspace) { - const fetchWS = async () => { - try { - const verifiedWs = cachedWorkspace - ? isValidWorkspace(cachedWorkspace, workspaces) - : false; - - API.workspacesById( - verifiedWs ? verifiedWs.id : workspaces[0].id - ).then((ws) => { - dispatch(setWorkspace(ws)); - }); - } catch (e) { - dispatch(setWorkspace(workspaces[0])); - } - }; - - fetchWS(); - } - }, [workspaces]); - // Set current params const params = useParams(); diff --git a/src/features/navigation/cachedStorage.ts b/src/features/navigation/cachedStorage.ts index 9bd8a52bb..507ea1439 100644 --- a/src/features/navigation/cachedStorage.ts +++ b/src/features/navigation/cachedStorage.ts @@ -4,7 +4,11 @@ const WORKSPACE_KEY = 'unguess_ws'; export const getWorkspaceFromLS = (): Workspace | false => { const ws = localStorage.getItem(WORKSPACE_KEY); - return ws ? JSON.parse(ws) : false; + try { + return JSON.parse(ws || 'invalid'); + } catch (e) { + return false; + } }; export const saveWorkspaceToLs = (workspace: Workspace): void => { diff --git a/src/features/navigation/navigationSlice.ts b/src/features/navigation/navigationSlice.ts index d1add2cac..c0c737b55 100644 --- a/src/features/navigation/navigationSlice.ts +++ b/src/features/navigation/navigationSlice.ts @@ -1,6 +1,7 @@ -import { appTheme } from 'src/app/theme'; import { createSlice } from '@reduxjs/toolkit'; +import { appTheme } from 'src/app/theme'; import { isMinMedia } from 'src/common/utils'; +import { saveWorkspaceToLs } from './cachedStorage'; import { NavigationState } from './types'; const initialState: NavigationState = { @@ -13,6 +14,7 @@ const navigationSlice = createSlice({ initialState, reducers: { setWorkspace: (state, action) => { + saveWorkspaceToLs(action.payload); state.activeWorkspace = action.payload; }, toggleSidebar: (state) => { diff --git a/src/hooks/useActiveWorkspace.ts b/src/hooks/useActiveWorkspace.ts new file mode 100644 index 000000000..91cde0f40 --- /dev/null +++ b/src/hooks/useActiveWorkspace.ts @@ -0,0 +1,52 @@ +/* eslint-disable no-debugger */ +import { useEffect, useState } from 'react'; +import { useAppSelector } from 'src/app/hooks'; +import { Workspace, useGetWorkspacesQuery } from 'src/features/api'; +import { getWorkspaceFromLS } from 'src/features/navigation/cachedStorage'; + +export const useActiveWorkspace = () => { + const [result, setResult] = useState(); + const { data: workspaces, isLoading } = useGetWorkspacesQuery({ + orderBy: 'company', + }); + const activeWorkspace = useAppSelector( + (state) => state.navigation.activeWorkspace + ); + + useEffect(() => { + if (activeWorkspace) { + setResult(activeWorkspace); + return; + } + + if (result) return; + + if ( + isLoading || + !workspaces || + !workspaces?.items || + workspaces.items.length === 0 + ) + return; + + const cachedWorkspace = getWorkspaceFromLS(); + if ( + cachedWorkspace && + workspaces.items.map((w) => w.id).includes(cachedWorkspace.id) + ) { + setResult(cachedWorkspace); + return; + } + + if ( + !isLoading && + workspaces && + workspaces.items && + workspaces.items.length > 0 + ) { + setResult(workspaces.items[0]); + } + }, [activeWorkspace, workspaces, isLoading]); + + return { activeWorkspace: result }; +}; diff --git a/src/hooks/useGTMevent.ts b/src/hooks/useGTMevent.ts index 01fe9cfd1..605f5e44c 100644 --- a/src/hooks/useGTMevent.ts +++ b/src/hooks/useGTMevent.ts @@ -1,6 +1,7 @@ import { useCallback } from 'react'; import TagManager from 'react-gtm-module'; import { useAppSelector } from 'src/app/hooks'; +import { useActiveWorkspace } from './useActiveWorkspace'; export interface GTMEventData { event: string; @@ -9,7 +10,7 @@ export interface GTMEventData { export const useSendGTMevent = () => { const { userData: user } = useAppSelector((state) => state.user); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const callback = useCallback( (data: GTMEventData) => { diff --git a/src/pages/Bugform/index.tsx b/src/pages/Bugform/index.tsx new file mode 100644 index 000000000..d2e23571a --- /dev/null +++ b/src/pages/Bugform/index.tsx @@ -0,0 +1,21 @@ +import IframeResizer from 'iframe-resizer-react'; +import { useParams, useSearchParams } from 'react-router-dom'; +import { Header } from 'src/common/components/navigation/header/header'; + +const BugForm = () => { + const { campaignId } = useParams<{ campaignId: string }>(); + const [query] = useSearchParams(); + const token = query.get('token') || ''; + return ( +
+
+ +
+ ); +}; + +export default BugForm; diff --git a/src/pages/Bugs/PageHeader/Tools/UniqueBugsCounter.tsx b/src/pages/Bugs/PageHeader/Tools/UniqueBugsCounter.tsx index 02559a2aa..99591d2b3 100644 --- a/src/pages/Bugs/PageHeader/Tools/UniqueBugsCounter.tsx +++ b/src/pages/Bugs/PageHeader/Tools/UniqueBugsCounter.tsx @@ -1,8 +1,8 @@ -import { Trans } from 'react-i18next'; import { MD, Span } from '@appquality/unguess-design-system'; -import styled from 'styled-components'; +import { Trans } from 'react-i18next'; import { appTheme } from 'src/app/theme'; -import { useUniqueBugs } from 'src/pages/Campaign/widgets/UniqueBugs/useUniqueBugs'; +import styled from 'styled-components'; +import { useUniqueBugs } from './useUniqueBugs'; const CounterContainer = styled.div` display: inline-block; diff --git a/src/pages/Campaign/widgets/UniqueBugs/useUniqueBugs.tsx b/src/pages/Bugs/PageHeader/Tools/useUniqueBugs.tsx similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs/useUniqueBugs.tsx rename to src/pages/Bugs/PageHeader/Tools/useUniqueBugs.tsx diff --git a/src/pages/Campaign/CampaignPage.tsx b/src/pages/Campaign/CampaignPage.tsx new file mode 100644 index 000000000..7fc71e0ee --- /dev/null +++ b/src/pages/Campaign/CampaignPage.tsx @@ -0,0 +1,85 @@ +import { Grid, Row } from '@appquality/unguess-design-system'; +import { useEffect } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { useAppDispatch } from 'src/app/hooks'; +import { LayoutWrapper } from 'src/common/components/LayoutWrapper'; +import { useGetCampaignWithWorkspaceQuery } from 'src/features/api/customEndpoints/getCampaignWithWorkspace'; + +import { Page } from 'src/features/templates/Page'; +import { useCampaignAnalytics } from 'src/hooks/useCampaignAnalytics'; +import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; +import { + setCampaignId, + setPermissionSettingsTitle, + setWorkspace, +} from '../../features/navigation/navigationSlice'; +import CampaignPageHeader from './pageHeader'; +import { HeaderLoader } from './pageHeaderLoading'; + +const CampaignPage = ({ children }: { children: React.ReactNode }) => { + const navigate = useNavigate(); + const notFoundRoute = useLocalizeRoute('oops'); + const { campaignId } = useParams(); + const dispatch = useAppDispatch(); + + if (!campaignId || Number.isNaN(Number(campaignId))) { + navigate(notFoundRoute); + } + + useCampaignAnalytics(campaignId); + + const { + isLoading: isLoadingCampaign, + isFetching: isFetchingCampaign, + isError: isErrorCampaign, + data: { campaign, workspace } = {}, + } = useGetCampaignWithWorkspaceQuery({ + cid: campaignId?.toString() ?? '0', + }); + + if (isErrorCampaign) { + navigate(notFoundRoute); + } + + useEffect(() => { + if (workspace) { + dispatch(setWorkspace(workspace)); + } + }, [workspace, dispatch]); + + useEffect(() => { + if (campaign) { + dispatch(setPermissionSettingsTitle(campaign.customer_title)); + dispatch(setCampaignId(campaign.id)); + } + + return () => { + dispatch(setPermissionSettingsTitle(undefined)); + dispatch(setCampaignId(undefined)); + }; + }, [campaign]); + + if (!campaign) return null; + + return ( + + ) : ( + + ) + } + route="campaigns" + > + + + {children} + + + + ); +}; + +export default CampaignPage; diff --git a/src/pages/Campaign/navigation/ExternalLink.tsx b/src/pages/Campaign/ExternalLink.tsx similarity index 100% rename from src/pages/Campaign/navigation/ExternalLink.tsx rename to src/pages/Campaign/ExternalLink.tsx diff --git a/src/pages/Campaign/ReportRowLoading.tsx b/src/pages/Campaign/ReportRowLoading.tsx deleted file mode 100644 index 2fa9694e6..000000000 --- a/src/pages/Campaign/ReportRowLoading.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { - Col, - Row, - Skeleton, - SpecialCard, - theme, -} from '@appquality/unguess-design-system'; - -export const ReportRowLoading = () => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); diff --git a/src/pages/Campaign/index.tsx b/src/pages/Campaign/index.tsx index 5d8521efc..63319259c 100644 --- a/src/pages/Campaign/index.tsx +++ b/src/pages/Campaign/index.tsx @@ -1,221 +1,64 @@ -import { useEffect } from 'react'; -import { useAppDispatch } from 'src/app/hooks'; -import { Page } from 'src/features/templates/Page'; -import { Col, Grid, Row } from '@appquality/unguess-design-system'; -import { useNavigate, useParams } from 'react-router-dom'; -import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; -import { useGetCampaignsByCidReportsQuery } from 'src/features/api'; -import { useCampaignAnalytics } from 'src/hooks/useCampaignAnalytics'; -import { useTranslation } from 'react-i18next'; -import { LayoutWrapper } from 'src/common/components/LayoutWrapper'; -import { useGetCampaignWithWorkspaceQuery } from 'src/features/api/customEndpoints/getCampaignWithWorkspace'; -import CampaignPageHeader from './pageHeader'; -import { HeaderLoader } from './pageHeaderLoading'; -import { ReportRowLoading } from './ReportRowLoading'; -import { ReportRow } from './ReportRow'; -import { Navigation, NavigationLoading } from './navigation'; -import { UniqueBugs } from './widgets/UniqueBugs'; -import { Progress } from './widgets/Progress'; -import BugDistributionCard from './widgets/BugDistributionCard'; -import { EmptyState } from './EmptyState'; -import { SectionTitle } from './SectionTitle'; -import UniqueBugs4UseCase from './widgets/UniqueBugs4UseCase'; -import IncomingBugs from './widgets/IncomingBugs'; -import BugsByType from './widgets/BugsByType'; -import TotalBugsByOsAndDevices from './widgets/TotalBugsByOsAndDevices'; -import { WidgetSection } from './WidgetSection'; +import { Col } from '@appquality/unguess-design-system'; +import { useParams } from 'react-router-dom'; +import { StickyContainer } from 'src/common/components/StickyContainer'; import { - setCampaignId, - setPermissionSettingsTitle, - setWorkspace, -} from '../../features/navigation/navigationSlice'; + StickyNavItem, + StickyNavItemLabel, + StyledDivider, +} from 'src/common/components/navigation'; +import CampaignPage from './CampaignPage'; +import { EmptyState } from './EmptyState'; +import { useWidgets } from './useWidgets'; const Campaign = () => { - const navigate = useNavigate(); - const notFoundRoute = useLocalizeRoute('oops'); const { campaignId } = useParams(); - const { t } = useTranslation(); - const dispatch = useAppDispatch(); - - if (!campaignId || Number.isNaN(Number(campaignId))) { - navigate(notFoundRoute); - } - - useCampaignAnalytics(campaignId); - - const { - isLoading: isLoadingCampaign, - isFetching: isFetchingCampaign, - isError: isErrorCampaign, - data: { campaign, workspace } = {}, - } = useGetCampaignWithWorkspaceQuery({ - cid: campaignId?.toString() ?? '0', - }); - - const { - isLoading: isLoadingReports, - isFetching: isFetchingReports, - isError: isErrorReports, - data: reports, - } = useGetCampaignsByCidReportsQuery({ - cid: campaignId?.toString() ?? '0', + const { widgets } = useWidgets({ + campaignId: campaignId ? Number(campaignId) : 0, }); - - if (isErrorCampaign || isErrorReports) { - navigate(notFoundRoute); - } - - const isFunctional = - campaign?.family.name.toLocaleLowerCase() === 'functional'; - - const firstRowHeight = '540px'; - const secondRowHeight = '465px'; - - useEffect(() => { - if (campaign) { - dispatch(setPermissionSettingsTitle(campaign.customer_title)); - dispatch(setCampaignId(campaign.id)); - } - - return () => { - dispatch(setPermissionSettingsTitle(undefined)); - dispatch(setCampaignId(undefined)); - }; - }, [campaign]); - - useEffect(() => { - if (workspace) { - dispatch(setWorkspace(workspace)); - } - }, [workspace, dispatch]); + const { all, footers, items, itemsWithTitles } = widgets; return ( - - ) : ( - - ) - } - route="campaigns" - > - - - - {!campaign?.outputs?.includes('bugs') && - !reports?.length && - !isFunctional ? ( - - ) : ( - <> - - {isLoadingCampaign || - isFetchingCampaign || - isLoadingReports || - isFetchingReports ? ( - - ) : ( - - )} - - - {campaign?.outputs?.includes('bugs') && ( - <> - - - - - - - - - - - - {isFetchingCampaign ? undefined : ( - - )} - - - - - - - - - - - - - - - - - - - - - - - - - - )} - {reports && - campaign && - !isLoadingReports && - !isFetchingReports ? ( - - ) : ( - - )} - - - )} - - - - + + {all.length === 0 ? ( + + ) : ( + <> + + + {itemsWithTitles.map((widget) => { + switch (widget.type) { + case 'title': + return ( + {widget.title} + ); + case 'item': + return ( + + {widget.title} + + ); + default: + return null; + } + })} + {footers.length > 0 && } + {footers.map((widget) => widget.content)} + + + + {items.map((widget) => widget.content)} + + + )} + ); }; diff --git a/src/pages/Campaign/navigation/BugsNavigation/index.tsx b/src/pages/Campaign/navigation/BugsNavigation/index.tsx deleted file mode 100644 index 5e810dd24..000000000 --- a/src/pages/Campaign/navigation/BugsNavigation/index.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { useTranslation } from 'react-i18next'; -import { - StickyNavItemLabel, - StickyNavItem, -} from 'src/common/components/navigation'; - -export const BugsNavigation = ({ containerId }: { containerId?: string }) => { - const { t } = useTranslation(); - - return ( - <> - - {t('__CAMPAIGN_PAGE_NAVIGATION_BUG_ITEM_OVERVIEW_LABEL')} - - - {t('__CAMPAIGN_PAGE_NAVIGATION_BUG_GROUP_DETAILS_LABEL')} - - - {t('__CAMPAIGN_PAGE_NAVIGATION_BUG_ITEM_DETAILS_UNIQUE_BUGS_LABEL')} - - - {t('__CAMPAIGN_PAGE_NAVIGATION_BUG_ITEM_DETAILS_DEVICES_LABEL')} - - - ); -}; diff --git a/src/pages/Campaign/navigation/MediaNavigation/index.tsx b/src/pages/Campaign/navigation/MediaNavigation/index.tsx deleted file mode 100644 index f041eb487..000000000 --- a/src/pages/Campaign/navigation/MediaNavigation/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export const MediaNavigation = () =>
; diff --git a/src/pages/Campaign/navigation/NavigationLoading.tsx b/src/pages/Campaign/navigation/NavigationLoading.tsx deleted file mode 100644 index 21b1831d0..000000000 --- a/src/pages/Campaign/navigation/NavigationLoading.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { Skeleton } from '@appquality/unguess-design-system'; - -export const NavigationLoading = () => ; diff --git a/src/pages/Campaign/navigation/ReportNavigation/index.tsx b/src/pages/Campaign/navigation/ReportNavigation/index.tsx deleted file mode 100644 index b9bb98810..000000000 --- a/src/pages/Campaign/navigation/ReportNavigation/index.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { - StickyNavItem, - StickyNavItemLabel, -} from 'src/common/components/navigation'; -import { useTranslation } from 'react-i18next'; - -export const ReportNavigation = () => { - const { t } = useTranslation(); - return ( - <> - - {t('__CAMPAIGN_PAGE_NAVIGATION_BUG_GROUP_OTHER_LABEL')} - - - {t('__CAMPAIGN_PAGE_NAVIGATION_BUG_ITEM_OTHER_REPORTS_LABEL')} - - - ); -}; diff --git a/src/pages/Campaign/navigation/index.tsx b/src/pages/Campaign/navigation/index.tsx deleted file mode 100644 index a84b5de5e..000000000 --- a/src/pages/Campaign/navigation/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useTranslation } from 'react-i18next'; -import { StyledDivider } from 'src/common/components/navigation'; -import { CampaignWithOutput, Report } from 'src/features/api'; -import { StickyContainer } from 'src/common/components/StickyContainer'; -import { - getLocalizedFunctionalDashboardUrl, - getLocalizedUXDashboardUrl, -} from 'src/hooks/useLocalizeDashboardUrl'; -import i18n from 'src/i18n'; -import { NavigationLoading } from './NavigationLoading'; -import { BugsNavigation } from './BugsNavigation'; -import { MediaNavigation } from './MediaNavigation'; -import { ReportNavigation } from './ReportNavigation'; -import { ExternalLink } from './ExternalLink'; - -const Navigation = ({ - campaignId, - outputs, - reports, - isFunctional, -}: { - campaignId: number; - outputs: CampaignWithOutput['outputs']; - reports: Report[]; - isFunctional?: boolean; -}) => { - const { t } = useTranslation(); - - const hasBugs = outputs?.includes('bugs'); - const hasMedia = outputs?.includes('media'); - const hasReports = !!(reports.length || isFunctional); - - return ( - - {hasBugs && } - {hasMedia && } - {hasReports && } - {(hasBugs || hasMedia) && } - {hasBugs && ( - - {t('__CAMPAIGN_PAGE_NAVIGATION_BUG_EXTERNAL_LINK_LABEL')} - - )} - {hasMedia && ( - - {t('__CAMPAIGN_PAGE_NAVIGATION_MEDIA_EXTERNAL_LINK_LABEL')} - - )} - - ); -}; - -export { Navigation, NavigationLoading }; diff --git a/src/pages/Campaign/useWidgets/Experience/widgets.tsx b/src/pages/Campaign/useWidgets/Experience/widgets.tsx new file mode 100644 index 000000000..33458fbd5 --- /dev/null +++ b/src/pages/Campaign/useWidgets/Experience/widgets.tsx @@ -0,0 +1,29 @@ +import { useTranslation } from 'react-i18next'; +import { useGetCampaignsByCidQuery } from 'src/features/api'; +import { getLocalizedUXDashboardUrl } from 'src/hooks/useLocalizeDashboardUrl'; +import { ExternalLink } from '../../ExternalLink'; + +export const widgets = ({ campaignId }: { campaignId: number }) => { + const { t, i18n } = useTranslation(); + const { data: campaign } = useGetCampaignsByCidQuery({ + cid: campaignId.toString(), + }); + + const showExperience = !!campaign?.outputs?.includes('media'); + + if (!showExperience || !campaign) return []; + + return [ + { + content: ( + + {t('__CAMPAIGN_PAGE_NAVIGATION_MEDIA_EXTERNAL_LINK_LABEL')} + + ), + type: 'footer' as const, + }, + ]; +}; diff --git a/src/pages/Campaign/useWidgets/Functional/CampaignOverview.tsx b/src/pages/Campaign/useWidgets/Functional/CampaignOverview.tsx new file mode 100644 index 000000000..99a4c9ff2 --- /dev/null +++ b/src/pages/Campaign/useWidgets/Functional/CampaignOverview.tsx @@ -0,0 +1,36 @@ +import { Col } from '@appquality/unguess-design-system'; +import { useTranslation } from 'react-i18next'; +import { Campaign } from 'src/features/api'; +import { SectionTitle } from '../../SectionTitle'; +import { WidgetSection } from '../../WidgetSection'; +import BugDistributionCard from './widgets/BugDistributionCard'; +import { Progress } from './widgets/Progress'; +import { UniqueBugs } from './widgets/UniqueBugs'; + +export const CampaignOverview = ({ + id, + campaign, +}: { + id: string; + campaign: Campaign; +}) => { + const { t } = useTranslation(); + return ( + + + + + + + + + + + + + + + ); +}; diff --git a/src/pages/Campaign/useWidgets/Functional/DevicesAndTypes.tsx b/src/pages/Campaign/useWidgets/Functional/DevicesAndTypes.tsx new file mode 100644 index 000000000..437a87de5 --- /dev/null +++ b/src/pages/Campaign/useWidgets/Functional/DevicesAndTypes.tsx @@ -0,0 +1,98 @@ +import { Col } from '@appquality/unguess-design-system'; +import { useTranslation } from 'react-i18next'; +import { Campaign } from 'src/features/api'; +import { SectionTitle } from '../../SectionTitle'; +import { WidgetSection } from '../../WidgetSection'; +import BugDistributionCard from './widgets/BugDistributionCard'; +import BugsByType from './widgets/BugsByType'; +import IncomingBugs from './widgets/IncomingBugs'; +import { Progress } from './widgets/Progress'; +import TotalBugsByOsAndDevices from './widgets/TotalBugsByOsAndDevices'; +import { UniqueBugs } from './widgets/UniqueBugs'; +import UniqueBugs4UseCase from './widgets/UniqueBugs4UseCase'; + +export const CampaignOverview = ({ + id, + campaign, +}: { + id: string; + campaign: Campaign; +}) => { + const { t } = useTranslation(); + return ( + + + + + + + + + + + + + + + ); +}; + +export const UniqueBugsSection = ({ + id, + campaign, +}: { + id: string; + campaign: Campaign; +}) => { + const { t } = useTranslation(); + const firstRowHeight = '540px'; + return ( + + + + + + + + + + + + ); +}; + +export const DevicesAndTypes = ({ + id, + campaign, +}: { + id: string; + campaign: Campaign; +}) => { + const { t } = useTranslation(); + const secondRowHeight = '465px'; + + return ( + + + + + + + + + + + + ); +}; diff --git a/src/pages/Campaign/useWidgets/Functional/UniqueBugsSection.tsx b/src/pages/Campaign/useWidgets/Functional/UniqueBugsSection.tsx new file mode 100644 index 000000000..fcc9dd495 --- /dev/null +++ b/src/pages/Campaign/useWidgets/Functional/UniqueBugsSection.tsx @@ -0,0 +1,34 @@ +import { Col } from '@appquality/unguess-design-system'; +import { useTranslation } from 'react-i18next'; +import { Campaign } from 'src/features/api'; +import { SectionTitle } from '../../SectionTitle'; +import { WidgetSection } from '../../WidgetSection'; +import IncomingBugs from './widgets/IncomingBugs'; +import UniqueBugs4UseCase from './widgets/UniqueBugs4UseCase'; + +export const UniqueBugsSection = ({ + id, + campaign, +}: { + id: string; + campaign: Campaign; +}) => { + const { t } = useTranslation(); + const firstRowHeight = '540px'; + return ( + + + + + + + + + + + + ); +}; diff --git a/src/pages/Campaign/useWidgets/Functional/widgets.tsx b/src/pages/Campaign/useWidgets/Functional/widgets.tsx new file mode 100644 index 000000000..cbb5aae98 --- /dev/null +++ b/src/pages/Campaign/useWidgets/Functional/widgets.tsx @@ -0,0 +1,59 @@ +import { useTranslation } from 'react-i18next'; +import { useGetCampaignsByCidQuery } from 'src/features/api'; +import { getLocalizedFunctionalDashboardUrl } from 'src/hooks/useLocalizeDashboardUrl'; +import { ExternalLink } from '../../ExternalLink'; +import { CampaignOverview } from './CampaignOverview'; +import { DevicesAndTypes } from './DevicesAndTypes'; +import { UniqueBugsSection } from './UniqueBugsSection'; + +export const widgets = ({ campaignId }: { campaignId: number }) => { + const { t, i18n } = useTranslation(); + const { data: campaign } = useGetCampaignsByCidQuery({ + cid: campaignId.toString(), + }); + + const showFunctional = !!campaign?.outputs?.includes('bugs'); + + if (!showFunctional || !campaign) return []; + + return [ + { + id: 'campaign-overview', + content: , + title: t('__CAMPAIGN_PAGE_NAVIGATION_BUG_ITEM_OVERVIEW_LABEL'), + type: 'item' as const, + }, + { + title: t('__CAMPAIGN_PAGE_NAVIGATION_BUG_GROUP_DETAILS_LABEL'), + type: 'title' as const, + }, + { + id: 'unique-bug-distribution', + content: ( + + ), + title: t('__CAMPAIGN_PAGE_NAVIGATION_BUG_ITEM_DETAILS_UNIQUE_BUGS_LABEL'), + type: 'item' as const, + }, + { + id: 'devices-and-types', + content: , + type: 'item' as const, + title: t('__CAMPAIGN_PAGE_NAVIGATION_BUG_ITEM_DETAILS_DEVICES_LABEL'), + }, + { + content: ( + + {t('__CAMPAIGN_PAGE_NAVIGATION_BUG_EXTERNAL_LINK_LABEL')} + + ), + type: 'footer' as const, + }, + ]; +}; diff --git a/src/pages/Campaign/widgets/BugDistributionCard/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/BugDistributionCard/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/BugDistributionCard/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/BugDistributionCard/index.tsx diff --git a/src/pages/Campaign/widgets/BugDistributionCard/useBugs.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/BugDistributionCard/useBugs.tsx similarity index 100% rename from src/pages/Campaign/widgets/BugDistributionCard/useBugs.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/BugDistributionCard/useBugs.tsx diff --git a/src/pages/Campaign/widgets/BugsByType/ChartTotalBugsByType.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/ChartTotalBugsByType.tsx similarity index 100% rename from src/pages/Campaign/widgets/BugsByType/ChartTotalBugsByType.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/ChartTotalBugsByType.tsx diff --git a/src/pages/Campaign/widgets/BugsByType/ListTotalBugByType.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/ListTotalBugByType.tsx similarity index 100% rename from src/pages/Campaign/widgets/BugsByType/ListTotalBugByType.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/ListTotalBugByType.tsx diff --git a/src/pages/Campaign/widgets/BugsByType/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/BugsByType/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/index.tsx diff --git a/src/pages/Campaign/widgets/BugsByType/useBugsByType.ts b/src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/useBugsByType.ts similarity index 100% rename from src/pages/Campaign/widgets/BugsByType/useBugsByType.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/useBugsByType.ts diff --git a/src/pages/Campaign/widgets/BugsByType/useCampaignBugTypes.ts b/src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/useCampaignBugTypes.ts similarity index 100% rename from src/pages/Campaign/widgets/BugsByType/useCampaignBugTypes.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/BugsByType/useCampaignBugTypes.ts diff --git a/src/pages/Campaign/widgets/IncomingBugs/DuplicateBugs/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/DuplicateBugs/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/IncomingBugs/DuplicateBugs/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/DuplicateBugs/index.tsx diff --git a/src/pages/Campaign/widgets/IncomingBugs/DuplicateBugs/useBugsByDuplicates.ts b/src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/DuplicateBugs/useBugsByDuplicates.ts similarity index 100% rename from src/pages/Campaign/widgets/IncomingBugs/DuplicateBugs/useBugsByDuplicates.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/DuplicateBugs/useBugsByDuplicates.ts diff --git a/src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/EmptyState.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/EmptyState.tsx similarity index 100% rename from src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/EmptyState.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/EmptyState.tsx diff --git a/src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/UnreadBugsWrapper.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/UnreadBugsWrapper.tsx similarity index 100% rename from src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/UnreadBugsWrapper.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/UnreadBugsWrapper.tsx diff --git a/src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/assets/empty.svg b/src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/assets/empty.svg similarity index 100% rename from src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/assets/empty.svg rename to src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/assets/empty.svg diff --git a/src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/index.tsx diff --git a/src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/useUnreadBugs.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/useUnreadBugs.tsx similarity index 100% rename from src/pages/Campaign/widgets/IncomingBugs/UnreadBugs/useUnreadBugs.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/UnreadBugs/useUnreadBugs.tsx diff --git a/src/pages/Campaign/widgets/IncomingBugs/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/IncomingBugs/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/IncomingBugs/index.tsx diff --git a/src/pages/Campaign/widgets/List/Columns.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/List/Columns.tsx similarity index 100% rename from src/pages/Campaign/widgets/List/Columns.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/List/Columns.tsx diff --git a/src/pages/Campaign/widgets/List/ListItem.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/List/ListItem.tsx similarity index 100% rename from src/pages/Campaign/widgets/List/ListItem.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/List/ListItem.tsx diff --git a/src/pages/Campaign/widgets/List/Pagination.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/List/Pagination.tsx similarity index 100% rename from src/pages/Campaign/widgets/List/Pagination.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/List/Pagination.tsx diff --git a/src/pages/Campaign/widgets/List/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/List/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/List/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/List/index.tsx diff --git a/src/pages/Campaign/widgets/List/type.ts b/src/pages/Campaign/useWidgets/Functional/widgets/List/type.ts similarity index 100% rename from src/pages/Campaign/widgets/List/type.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/List/type.ts diff --git a/src/pages/Campaign/widgets/Progress/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/Progress/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/Progress/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/Progress/index.tsx diff --git a/src/pages/Campaign/widgets/Progress/useWidgetData.ts b/src/pages/Campaign/useWidgets/Functional/widgets/Progress/useWidgetData.ts similarity index 100% rename from src/pages/Campaign/widgets/Progress/useWidgetData.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/Progress/useWidgetData.ts diff --git a/src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/getChildrenValue.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/getChildrenValue.tsx similarity index 100% rename from src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/getChildrenValue.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/getChildrenValue.tsx diff --git a/src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/index.tsx diff --git a/src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/types.ts b/src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/types.ts similarity index 100% rename from src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/types.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/types.ts diff --git a/src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/useBugsByDevices.ts b/src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/useBugsByDevices.ts similarity index 100% rename from src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/useBugsByDevices.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ChartTotalBugsByDevice/useBugsByDevices.ts diff --git a/src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ListTotalBugsByDevice/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ListTotalBugsByDevice/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ListTotalBugsByDevice/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ListTotalBugsByDevice/index.tsx diff --git a/src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ListTotalBugsByDevice/useListBugsByDevice.ts b/src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ListTotalBugsByDevice/useListBugsByDevice.ts similarity index 100% rename from src/pages/Campaign/widgets/TotalBugsByOsAndDevices/ListTotalBugsByDevice/useListBugsByDevice.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/ListTotalBugsByDevice/useListBugsByDevice.ts diff --git a/src/pages/Campaign/widgets/TotalBugsByOsAndDevices/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/TotalBugsByOsAndDevices/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/TotalBugsByOsAndDevices/index.tsx diff --git a/src/pages/Campaign/widgets/UniqueBugs/Trend.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs/Trend.tsx similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs/Trend.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs/Trend.tsx diff --git a/src/pages/Campaign/widgets/UniqueBugs/WaffleTooltip.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs/WaffleTooltip.tsx similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs/WaffleTooltip.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs/WaffleTooltip.tsx diff --git a/src/pages/Campaign/widgets/UniqueBugs/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs/index.tsx diff --git a/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs/useUniqueBugs.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs/useUniqueBugs.tsx new file mode 100644 index 000000000..177ef6e3f --- /dev/null +++ b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs/useUniqueBugs.tsx @@ -0,0 +1,38 @@ +import { useGetCampaignsByCidWidgetsQuery } from 'src/features/api'; + +const useUniqueBugs = (campaignId: number) => { + const { data, isLoading, isFetching, isError } = + useGetCampaignsByCidWidgetsQuery({ + cid: campaignId.toString(), + s: 'unique-bugs', + updateTrend: true, + }); + + const { data: results, kind } = data || {}; + + if (results && kind === 'campaignUniqueBugs') { + const { total: totalBugs, unique: uniqueBugs, trend: trendBugs } = results; + + return { + totalBugs, + uniqueBugs, + trendBugs, + uniquePercentage: Math.floor((uniqueBugs / totalBugs) * 100), + isLoading, + isFetching, + isError, + }; + } + + return { + totalBugs: 0, + uniqueBugs: 0, + trendBugs: 0, + uniquePercentage: 0, + isLoading, + isFetching, + isError, + }; +}; + +export { useUniqueBugs }; diff --git a/src/pages/Campaign/widgets/UniqueBugs4UseCase/Chart/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/Chart/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs4UseCase/Chart/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/Chart/index.tsx diff --git a/src/pages/Campaign/widgets/UniqueBugs4UseCase/List/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/List/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs4UseCase/List/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/List/index.tsx diff --git a/src/pages/Campaign/widgets/UniqueBugs4UseCase/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs4UseCase/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/index.tsx diff --git a/src/pages/Campaign/widgets/UniqueBugs4UseCase/types.ts b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/types.ts similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs4UseCase/types.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/types.ts diff --git a/src/pages/Campaign/widgets/UniqueBugs4UseCase/useBugsByUsecase.ts b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/useBugsByUsecase.ts similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs4UseCase/useBugsByUsecase.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/useBugsByUsecase.ts diff --git a/src/pages/Campaign/widgets/UniqueBugs4UseCase/useMaxItems.ts b/src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/useMaxItems.ts similarity index 100% rename from src/pages/Campaign/widgets/UniqueBugs4UseCase/useMaxItems.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/UniqueBugs4UseCase/useMaxItems.ts diff --git a/src/pages/Campaign/widgets/widgetCards/BasicWidget.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/BasicWidget.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/BasicWidget.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/BasicWidget.tsx diff --git a/src/pages/Campaign/widgets/widgetCards/FlipCard/FlipCardBody.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/FlipCardBody.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/FlipCard/FlipCardBody.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/FlipCardBody.tsx diff --git a/src/pages/Campaign/widgets/widgetCards/FlipCard/FlipCardHeader.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/FlipCardHeader.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/FlipCard/FlipCardHeader.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/FlipCardHeader.tsx diff --git a/src/pages/Campaign/widgets/widgetCards/FlipCard/context/FlipCardContext.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/context/FlipCardContext.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/FlipCard/context/FlipCardContext.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/context/FlipCardContext.tsx diff --git a/src/pages/Campaign/widgets/widgetCards/FlipCard/index.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/index.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/FlipCard/index.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/index.tsx diff --git a/src/pages/Campaign/widgets/widgetCards/FlipCard/types.ts b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/types.ts similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/FlipCard/types.ts rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/FlipCard/types.ts diff --git a/src/pages/Campaign/widgets/widgetCards/common/CapitalizeFirstLetter.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/common/CapitalizeFirstLetter.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/common/CapitalizeFirstLetter.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/common/CapitalizeFirstLetter.tsx diff --git a/src/pages/Campaign/widgets/widgetCards/common/StyledSpecialCard.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/common/StyledSpecialCard.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/common/StyledSpecialCard.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/common/StyledSpecialCard.tsx diff --git a/src/pages/Campaign/widgets/widgetCards/common/WidgetCardFooter.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/common/WidgetCardFooter.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/common/WidgetCardFooter.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/common/WidgetCardFooter.tsx diff --git a/src/pages/Campaign/widgets/widgetCards/common/WidgetCardHeader.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/common/WidgetCardHeader.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetCards/common/WidgetCardHeader.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetCards/common/WidgetCardHeader.tsx diff --git a/src/pages/Campaign/widgets/widgetLoader.tsx b/src/pages/Campaign/useWidgets/Functional/widgets/widgetLoader.tsx similarity index 100% rename from src/pages/Campaign/widgets/widgetLoader.tsx rename to src/pages/Campaign/useWidgets/Functional/widgets/widgetLoader.tsx diff --git a/src/pages/Campaign/ReportRow.tsx b/src/pages/Campaign/useWidgets/Report/ReportRow.tsx similarity index 51% rename from src/pages/Campaign/ReportRow.tsx rename to src/pages/Campaign/useWidgets/Report/ReportRow.tsx index b6540bf09..b8529f0d4 100644 --- a/src/pages/Campaign/ReportRow.tsx +++ b/src/pages/Campaign/useWidgets/Report/ReportRow.tsx @@ -1,10 +1,13 @@ import { + Button, Col, Row, SpecialCard, - Button, theme, } from '@appquality/unguess-design-system'; +import { format } from 'date-fns'; +import { t } from 'i18next'; +import { ReactComponent as DownloadIcon } from 'src/assets/icons/download-stroke.svg'; import { ReactComponent as ArchiveIcon } from 'src/assets/icons/file-icon-archive.svg'; import { ReactComponent as BoardIcon } from 'src/assets/icons/file-icon-board.svg'; import { ReactComponent as DocumentIcon } from 'src/assets/icons/file-icon-document.svg'; @@ -13,13 +16,10 @@ import { ReactComponent as ExcelIcon } from 'src/assets/icons/file-icon-excel.sv import { ReactComponent as LinkIcon } from 'src/assets/icons/file-icon-link.svg'; import { ReactComponent as PdfIcon } from 'src/assets/icons/file-icon-pdf.svg'; import { ReactComponent as PresentationIcon } from 'src/assets/icons/file-icon-presentation.svg'; -import { ReactComponent as DownloadIcon } from 'src/assets/icons/download-stroke.svg'; import { ReactComponent as OpenLinkIcon } from 'src/assets/icons/new-window-stroke.svg'; -import { Campaign, Report } from 'src/features/api'; -import { format } from 'date-fns'; -import { t } from 'i18next'; import { BugsReportCard } from 'src/common/components/BugsReportCard'; -import { SectionTitle } from './SectionTitle'; +import { Campaign, Report } from 'src/features/api'; +import { SectionTitle } from '../../SectionTitle'; const getFileTypeName = (type: string, url: string) => { const urlHostname = new URL(url).hostname; @@ -76,18 +76,16 @@ const getFileTypeIcon = (type: string, url: string) => { export const ReportRow = ({ reports, campaign, - isFunctional, }: { - reports?: Report[]; + reports?: (Report | 'bugreport')[]; campaign: Campaign; - isFunctional?: boolean; }) => { const { id: campaignId, customer_title } = campaign; return (
- {(reports && reports.length) || isFunctional ? ( + {reports && reports.length ? ( ) : null} - {isFunctional && ( - - - - )} {reports && reports.length - ? reports.map((report) => ( - - - - {report.update_date ? ( - <> - {t('__CAMPAIGN_PAGE_REPORTS_CARDS_UPDATED_ON_LABEL')}{' '} - {format(new Date(report.update_date), 'dd/MM/yyyy')} - - ) : ( - <> - {t('__CAMPAIGN_PAGE_REPORTS_CARDS_UPLOADED_ON_LABEL')}{' '} - {format( - new Date(report.creation_date ?? ''), - 'dd/MM/yyyy' - )} - - )} - - - - {getFileTypeIcon(report.file_type?.type ?? '', report.url)} - + ? reports.map((report) => + report === 'bugreport' ? ( + + + + ) : ( + + + + {report.update_date ? ( + <> + {t('__CAMPAIGN_PAGE_REPORTS_CARDS_UPDATED_ON_LABEL')}{' '} + {format(new Date(report.update_date), 'dd/MM/yyyy')} + + ) : ( + <> + {t('__CAMPAIGN_PAGE_REPORTS_CARDS_UPLOADED_ON_LABEL')}{' '} + {format( + new Date(report.creation_date ?? ''), + 'dd/MM/yyyy' + )} + + )} + - - - {getFileTypeName( + + {getFileTypeIcon( report.file_type?.type ?? '', report.url )} - - - {report.title} - - + - - - - - - )) + + + {report.title} + + + + + + + + + ) + ) : null}
diff --git a/src/pages/Campaign/useWidgets/Report/widgets.tsx b/src/pages/Campaign/useWidgets/Report/widgets.tsx new file mode 100644 index 000000000..e67108b61 --- /dev/null +++ b/src/pages/Campaign/useWidgets/Report/widgets.tsx @@ -0,0 +1,49 @@ +import { useTranslation } from 'react-i18next'; +import { + useGetCampaignsByCidQuery, + useGetCampaignsByCidReportsQuery, +} from 'src/features/api'; +import { ReportRow } from './ReportRow'; + +export const widgets = ({ campaignId }: { campaignId: number }) => { + const { t } = useTranslation(); + const { data: campaign } = useGetCampaignsByCidQuery({ + cid: campaignId.toString(), + }); + + const { + data: reports, + isLoading: isLoadingReports, + isFetching: isFetchingReports, + } = useGetCampaignsByCidReportsQuery({ + cid: campaignId.toString(), + }); + const reportList = [ + ...(reports ?? []), + ...(campaign?.family.name.toLocaleLowerCase() === 'functional' + ? ['bugreport' as const] + : []), + ]; + + const showReport = !!( + reportList && + campaign && + !isLoadingReports && + !isFetchingReports + ); + + if (!showReport || !campaign) return []; + + return [ + { + title: t('__CAMPAIGN_PAGE_NAVIGATION_BUG_GROUP_OTHER_LABEL'), + type: 'title' as const, + }, + { + id: 'reports', + content: , + type: 'item' as const, + title: t('__CAMPAIGN_PAGE_NAVIGATION_BUG_ITEM_OTHER_REPORTS_LABEL'), + }, + ]; +}; diff --git a/src/pages/Campaign/useWidgets/index.tsx b/src/pages/Campaign/useWidgets/index.tsx new file mode 100644 index 000000000..47366b2f1 --- /dev/null +++ b/src/pages/Campaign/useWidgets/index.tsx @@ -0,0 +1,48 @@ +import { useGetCampaignsByCidQuery } from 'src/features/api'; +import { widgets as experienceWidgets } from './Experience/widgets'; +import { widgets as functionalWidgets } from './Functional/widgets'; +import { widgets as reportWidgets } from './Report/widgets'; + +export const useWidgets = ({ campaignId }: { campaignId: number }) => { + const { data: campaign } = useGetCampaignsByCidQuery({ + cid: campaignId.toString(), + }); + const functional = functionalWidgets({ + campaignId, + }); + + const experience = experienceWidgets({ + campaignId, + }); + + const reports = reportWidgets({ + campaignId, + }); + + if (!campaign) + return { + widgets: { all: [], footers: [], items: [], itemsWithTitles: [] }, + isLoading: false, + isError: false, + }; + + const result = [...functional, ...experience, ...reports]; + return { + widgets: { + all: result, + footers: result.filter( + (widget): widget is typeof widget & { type: 'footer' } => + widget.type === 'footer' + ), + + items: result.filter( + (widget): widget is typeof widget & { type: 'item' } => + widget.type === 'item' + ), + itemsWithTitles: result.filter( + (widget): widget is typeof widget & { type: 'item' | 'title' } => + widget.type === 'item' || widget.type === 'title' + ), + }, + }; +}; diff --git a/src/pages/Dashboard/ActionCards.tsx b/src/pages/Dashboard/ActionCards.tsx index a3c077e4e..22b202812 100644 --- a/src/pages/Dashboard/ActionCards.tsx +++ b/src/pages/Dashboard/ActionCards.tsx @@ -1,14 +1,19 @@ import { Col, - Row, Paragraph, - theme, ProductCard, + Row, TextDescription, + theme, } from '@appquality/unguess-design-system'; +import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useAppDispatch, useAppSelector } from 'src/app/hooks'; import { ReactComponent as ExpressIcon } from 'src/assets/icons/express-icon.svg'; +import { extractStrapiData } from 'src/common/getStrapiData'; +import { hasEnoughCoins, isMinMedia, toggleChat } from 'src/common/utils'; +import { useGetProjectsByPidQuery } from 'src/features/api'; +import { useGeti18nExpressTypesQuery } from 'src/features/backoffice/strapi'; import { lockProject, openDrawer, @@ -16,12 +21,8 @@ import { setExpressProject, setExpressTypeId, } from 'src/features/express/expressSlice'; -import { useGetProjectsByPidQuery } from 'src/features/api'; -import { hasEnoughCoins, isMinMedia, toggleChat } from 'src/common/utils'; -import { useEffect } from 'react'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; import i18n from 'src/i18n'; -import { useGeti18nExpressTypesQuery } from 'src/features/backoffice/strapi'; -import { extractStrapiData } from 'src/common/getStrapiData'; import { ExpressWizardContainer } from '../ExpressWizard'; import { ExpressDrawer } from '../ExpressWizard/drawer'; import { CardRowLoading } from './CardRowLoading'; @@ -30,7 +31,7 @@ export const ActionCards = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const { projectId } = useAppSelector((state) => state.filters); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); // TODO: this is a hack to get the express type id without a service attached const { diff --git a/src/pages/Dashboard/Counters.tsx b/src/pages/Dashboard/Counters.tsx index 51ff56192..c21802444 100644 --- a/src/pages/Dashboard/Counters.tsx +++ b/src/pages/Dashboard/Counters.tsx @@ -1,13 +1,13 @@ import { Skeleton } from '@appquality/unguess-design-system'; -import { StatusMeta } from 'src/common/components/meta/StatusMeta'; import { useParams } from 'react-router-dom'; -import { useAppSelector } from 'src/app/hooks'; +import { PageMeta } from 'src/common/components/PageMeta'; +import { Pipe } from 'src/common/components/Pipe'; +import { StatusMeta } from 'src/common/components/meta/StatusMeta'; import { Campaign, useGetWorkspacesByWidCampaignsQuery, } from 'src/features/api'; -import { PageMeta } from 'src/common/components/PageMeta'; -import { Pipe } from 'src/common/components/Pipe'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; const getCounterValues = (campaigns: Campaign[], projectId?: string) => { const prjId = @@ -43,9 +43,7 @@ const getCounterValues = (campaigns: Campaign[], projectId?: string) => { }; export const Counters = () => { - const activeWorkspace = useAppSelector( - (state) => state.navigation.activeWorkspace - ); + const { activeWorkspace } = useActiveWorkspace(); const { projectId } = useParams(); diff --git a/src/pages/Dashboard/SuggestedCampaigns.tsx b/src/pages/Dashboard/SuggestedCampaigns.tsx index a38ae5e77..a9aabd64b 100644 --- a/src/pages/Dashboard/SuggestedCampaigns.tsx +++ b/src/pages/Dashboard/SuggestedCampaigns.tsx @@ -1,13 +1,13 @@ import { Col, - Row, Paragraph, - theme, + Row, TextDescription, + theme, } from '@appquality/unguess-design-system'; import { useTranslation } from 'react-i18next'; -import { useAppSelector } from 'src/app/hooks'; import { useGetWorkspacesByWidCampaignsQuery } from 'src/features/api'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; import { getLocalizeDashboardRoute } from 'src/hooks/useLocalizeDashboardUrl'; import { CampaignItem } from './CampaignItem'; import { CardsContainer, StyledRow } from './CardContainer'; @@ -16,7 +16,7 @@ import { CampaignActionProps } from './types'; export const SuggestedCampaigns = () => { const { t } = useTranslation(); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const campaigns = useGetWorkspacesByWidCampaignsQuery({ wid: activeWorkspace?.id.toString() || '', diff --git a/src/pages/Dashboard/campaigns-list/index.tsx b/src/pages/Dashboard/campaigns-list/index.tsx index a11779875..7b4892055 100644 --- a/src/pages/Dashboard/campaigns-list/index.tsx +++ b/src/pages/Dashboard/campaigns-list/index.tsx @@ -1,29 +1,30 @@ import { Col, - theme, - Row, IconButton, + Row, Span, TextDescription, + theme, } from '@appquality/unguess-design-system'; +import { createSelector } from '@reduxjs/toolkit'; +import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useAppSelector } from 'src/app/hooks'; -import styled from 'styled-components'; import { ReactComponent as GridIcon } from 'src/assets/icons/grid.svg'; import { ReactComponent as ListIcon } from 'src/assets/icons/list.svg'; -import { useEffect, useMemo, useState } from 'react'; +import { useGetWorkspacesByWidCampaignsQuery } from 'src/features/api'; import { - selectGroupedCampaigns, selectFilteredCampaigns, + selectGroupedCampaigns, } from 'src/features/campaigns'; -import { useGetWorkspacesByWidCampaignsQuery } from 'src/features/api'; -import { createSelector } from '@reduxjs/toolkit'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; import useWindowSize from 'src/hooks/useWindowSize'; -import { CardList } from './list'; -import { TableList } from './table'; +import styled from 'styled-components'; import { Separator } from '../Separator'; -import { Filters } from '../filters'; import { EmptyResults } from '../emptyState'; +import { Filters } from '../filters'; +import { CardList } from './list'; +import { TableList } from './table'; const FloatRight = styled.div` float: right; @@ -32,9 +33,7 @@ const FloatRight = styled.div` export const CampaignsList = () => { const { t } = useTranslation(); - const activeWorkspace = useAppSelector( - (state) => state.navigation.activeWorkspace - ); + const { activeWorkspace } = useActiveWorkspace(); const { width } = useWindowSize(); const breakpointMd = parseInt(theme.breakpoints.md, 10); diff --git a/src/pages/ExpressWizard/index.tsx b/src/pages/ExpressWizard/index.tsx index 8117b2cee..2a4a0dfab 100644 --- a/src/pages/ExpressWizard/index.tsx +++ b/src/pages/ExpressWizard/index.tsx @@ -1,4 +1,3 @@ -import { useEffect, useRef, useState } from 'react'; import { Col, ContainerCard, @@ -8,7 +7,7 @@ import { Row, Stepper, } from '@appquality/unguess-design-system'; -import { appTheme } from 'src/app/theme'; +import { format } from 'date-fns'; import { Form, Formik, @@ -16,51 +15,53 @@ import { FormikProps, setNestedObjectValues, } from 'formik'; +import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useAppDispatch, useAppSelector } from 'src/app/hooks'; -import { - closeDrawer, - closeWizard, - resetWizard, - setExpressProject, -} from 'src/features/express/expressSlice'; -import * as Yup from 'yup'; -import styled from 'styled-components'; -import { - Project, - Campaign, - usePostCampaignsMutation, - usePostProjectsMutation, -} from 'src/features/api'; -import { - BASE_DATE_FORMAT, - ZAPIER_WEBHOOK_TRIGGER, - EXPRESS_4_CAMPAIGN_TYPE_ID, - EXPRESS_3_CAMPAIGN_TYPE_ID, - EXPRESS_2_CAMPAIGN_TYPE_ID, - EXPRESS_1_CAMPAIGN_TYPE_ID, -} from 'src/constants'; -import { format } from 'date-fns'; +import { appTheme } from 'src/app/theme'; import { createCrons, createPages, createTasks, createUseCases, } from 'src/common/campaigns'; -import { toggleChat } from 'src/common/utils'; -import i18n from 'src/i18n'; +import { LayoutWrapper } from 'src/common/components/LayoutWrapper'; import { extractStrapiData } from 'src/common/getStrapiData'; +import { toggleChat } from 'src/common/utils'; +import { + BASE_DATE_FORMAT, + EXPRESS_1_CAMPAIGN_TYPE_ID, + EXPRESS_2_CAMPAIGN_TYPE_ID, + EXPRESS_3_CAMPAIGN_TYPE_ID, + EXPRESS_4_CAMPAIGN_TYPE_ID, + ZAPIER_WEBHOOK_TRIGGER, +} from 'src/constants'; +import { + Campaign, + Project, + usePostCampaignsMutation, + usePostProjectsMutation, +} from 'src/features/api'; import { useGeti18nExpressTypesByIdQuery } from 'src/features/backoffice/strapi'; +import { + closeDrawer, + closeWizard, + resetWizard, + setExpressProject, +} from 'src/features/express/expressSlice'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; import { useSendGTMevent } from 'src/hooks/useGTMevent'; -import { LayoutWrapper } from 'src/common/components/LayoutWrapper'; +import i18n from 'src/i18n'; +import styled from 'styled-components'; +import * as Yup from 'yup'; import DiscardChangesModal from './ActionModals/DiscardChangesModal'; +import { getPlatform } from './getPlatform'; +import { reasonItems } from './steps/express-1/what'; import { ThankYouStep } from './steps/thankYou'; +import { StepItem, useExpressStep } from './steps/useSteps'; import { WizardHeader } from './wizardHeader'; -import { WizardModel } from './wizardModel'; import defaultValues from './wizardInitialValues'; -import { reasonItems } from './steps/express-1/what'; -import { getPlatform } from './getPlatform'; -import { StepItem, useExpressStep } from './steps/useSteps'; +import { WizardModel } from './wizardModel'; const StyledContainer = styled(ContainerCard)` position: sticky; @@ -132,7 +133,7 @@ export const ExpressWizardContainer = () => { const [stepperTitle, setStepperTitle] = useState(''); const { userData } = useAppSelector((state) => state.user); const { project } = useAppSelector((state) => state.express); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const { isWizardOpen, steps: draftSteps, diff --git a/src/pages/ExpressWizard/projectDropdown.tsx b/src/pages/ExpressWizard/projectDropdown.tsx index 60c652135..8a72c28ee 100644 --- a/src/pages/ExpressWizard/projectDropdown.tsx +++ b/src/pages/ExpressWizard/projectDropdown.tsx @@ -1,31 +1,29 @@ -import { useTranslation } from 'react-i18next'; -import { useAppDispatch, useAppSelector } from 'src/app/hooks'; import { - Dropdown, Autocomplete, - Menu, + Dropdown, Item, - Separator, - MediaFigure, MediaBody, + MediaFigure, + Menu, + Separator, Skeleton, } from '@appquality/unguess-design-system'; import { Field } from '@zendeskgarden/react-dropdowns'; +import { useTranslation } from 'react-i18next'; +import { useAppDispatch, useAppSelector } from 'src/app/hooks'; -import { ReactComponent as AddIcon } from 'src/assets/icons/grid-add.svg'; -import { ReactComponent as FolderIcon } from 'src/assets/icons/folder-icon.svg'; import { useEffect, useState } from 'react'; -import useDebounce from 'src/hooks/useDebounce'; -import { useGetWorkspacesByWidProjectsQuery, Project } from 'src/features/api'; +import { ReactComponent as FolderIcon } from 'src/assets/icons/folder-icon.svg'; +import { ReactComponent as AddIcon } from 'src/assets/icons/grid-add.svg'; +import { Project, useGetWorkspacesByWidProjectsQuery } from 'src/features/api'; import { setExpressProject } from 'src/features/express/expressSlice'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; +import useDebounce from 'src/hooks/useDebounce'; export const ProjectDropdown = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); - - const activeWorkspace = useAppSelector( - (state) => state.navigation.activeWorkspace - ); + const { activeWorkspace } = useActiveWorkspace(); const { project, projectLocked } = useAppSelector((state) => state.express); diff --git a/src/pages/ExpressWizard/wizardHeader.tsx b/src/pages/ExpressWizard/wizardHeader.tsx index db8727bdd..ec976a4a5 100644 --- a/src/pages/ExpressWizard/wizardHeader.tsx +++ b/src/pages/ExpressWizard/wizardHeader.tsx @@ -1,17 +1,17 @@ import { + Anchor, + InputToggle, Logo, Span, - InputToggle, - Anchor, } from '@appquality/unguess-design-system'; import { FormikProps } from 'formik'; import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; -import useWindowSize from 'src/hooks/useWindowSize'; -import styled from 'styled-components'; import { appTheme } from 'src/app/theme'; import { ReactComponent as ErrorIcon } from 'src/assets/icons/error-icon.svg'; -import { useAppSelector } from 'src/app/hooks'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; +import useWindowSize from 'src/hooks/useWindowSize'; +import styled from 'styled-components'; import { WizardModel } from './wizardModel'; export const Container = styled.div` @@ -39,7 +39,7 @@ export const WizardHeader = ({ onClose, ...props }: WizardHeaderProps) => { const { width } = useWindowSize(); const { t } = useTranslation(); const { getFieldProps, errors, validateForm } = props; - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const isDesktop = width > parseInt(appTheme.breakpoints.sm, 10); diff --git a/src/pages/Service/SingleServicePageHeader.tsx b/src/pages/Service/SingleServicePageHeader.tsx index cf82c1982..268e4c5f0 100644 --- a/src/pages/Service/SingleServicePageHeader.tsx +++ b/src/pages/Service/SingleServicePageHeader.tsx @@ -1,29 +1,29 @@ -import { ServiceResponse } from 'src/features/backoffice'; -import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; import { Anchor, + PageHeader, Paragraph, Span, - PageHeader, } from '@appquality/unguess-design-system'; -import { useNavigate } from 'react-router-dom'; import { Trans, useTranslation } from 'react-i18next'; -import { ReactComponent as TailoredIcon } from 'src/assets/icons/tailored-icon.svg'; -import { ReactComponent as ExpressIcon } from 'src/assets/icons/express-icon.svg'; +import { useNavigate } from 'react-router-dom'; +import { ReactComponent as EnvironmentIcon } from 'src/assets/icons/environment-icon.svg'; import { ReactComponent as ExperientialIcon } from 'src/assets/icons/experiential-icon.svg'; +import { ReactComponent as ExpressIcon } from 'src/assets/icons/express-icon.svg'; import { ReactComponent as FunctionalIcon } from 'src/assets/icons/functional-icon.svg'; -import { ReactComponent as EnvironmentIcon } from 'src/assets/icons/environment-icon.svg'; +import { ReactComponent as TailoredIcon } from 'src/assets/icons/tailored-icon.svg'; import { ReactComponent as TimeIcon } from 'src/assets/icons/time-icon.svg'; -import { extractStrapiData } from 'src/common/getStrapiData'; -import { PageTitle } from 'src/common/components/PageTitle'; -import { getLocalizedStrapiData } from 'src/common/utils'; -import i18n from 'src/i18n'; import { LayoutWrapper } from 'src/common/components/LayoutWrapper'; import { Meta } from 'src/common/components/Meta'; import { PageMeta } from 'src/common/components/PageMeta'; -import { useAppSelector } from 'src/app/hooks'; -import { ServiceExpressCta } from './ServiceExpressCta'; +import { PageTitle } from 'src/common/components/PageTitle'; +import { extractStrapiData } from 'src/common/getStrapiData'; +import { getLocalizedStrapiData } from 'src/common/utils'; +import { ServiceResponse } from 'src/features/backoffice'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; +import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; +import i18n from 'src/i18n'; import { ServiceContactUsCta } from './ServiceContactUsCta'; +import { ServiceExpressCta } from './ServiceExpressCta'; export const SingleServicePageHeader = ({ response, @@ -40,7 +40,7 @@ export const SingleServicePageHeader = ({ item: response, language: i18n.language, }); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); // Strapi response const days = service.duration_in_days ?? 3; diff --git a/src/pages/Service/index.tsx b/src/pages/Service/index.tsx index 6d5d0997b..a21bed62c 100644 --- a/src/pages/Service/index.tsx +++ b/src/pages/Service/index.tsx @@ -1,17 +1,18 @@ -import { Page } from 'src/features/templates/Page'; -import { useNavigate, useParams } from 'react-router-dom'; -import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; import { useMemo, useState } from 'react'; -import { ExpressWizardContainer } from 'src/pages/ExpressWizard'; -import { ExpressDrawer } from 'src/pages/ExpressWizard/drawer'; +import { useNavigate, useParams } from 'react-router-dom'; import { useAppDispatch, useAppSelector } from 'src/app/hooks'; -import { openWizard } from 'src/features/express/expressSlice'; -import { useGetFullServicesByIdQuery } from 'src/features/backoffice/strapi'; -import PageLoader from 'src/features/templates/PageLoader'; import { HubspotModal } from 'src/common/components/HubspotModal'; +import { LayoutWrapper } from 'src/common/components/LayoutWrapper'; import { checkHubspotURL, getLocalizedStrapiData } from 'src/common/utils'; +import { useGetFullServicesByIdQuery } from 'src/features/backoffice/strapi'; +import { openWizard } from 'src/features/express/expressSlice'; +import { Page } from 'src/features/templates/Page'; +import PageLoader from 'src/features/templates/PageLoader'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; +import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; import i18n from 'src/i18n'; -import { LayoutWrapper } from 'src/common/components/LayoutWrapper'; +import { ExpressWizardContainer } from 'src/pages/ExpressWizard'; +import { ExpressDrawer } from 'src/pages/ExpressWizard/drawer'; import { ServiceTimeline } from './ServiceTimeline'; import { SingleServicePageHeader } from './SingleServicePageHeader'; import { strapiParams } from './strapi'; @@ -22,7 +23,7 @@ const Service = () => { const dispatch = useAppDispatch(); const notFoundRoute = useLocalizeRoute('oops'); const [isModalOpen, setIsModalOpen] = useState(false); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const memoCsm = useMemo(() => activeWorkspace?.csm, [activeWorkspace]); diff --git a/src/pages/Services/CategoriesNav.tsx b/src/pages/Services/CategoriesNav.tsx index 4796d384d..03c0e9093 100644 --- a/src/pages/Services/CategoriesNav.tsx +++ b/src/pages/Services/CategoriesNav.tsx @@ -2,28 +2,29 @@ import { Anchor, Skeleton } from '@appquality/unguess-design-system'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import { useAppSelector } from 'src/app/hooks'; -import { CategoryResponse, ServiceResponse } from 'src/features/backoffice'; -import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; -import i18n from 'src/i18n'; -import { - useGeti18nCategoriesQuery, - useGeti18nServicesFeaturedQuery, -} from 'src/features/backoffice/strapi'; -import { hasEnoughCoins } from 'src/common/utils'; -import { extractStrapiData } from 'src/common/getStrapiData'; import { StickyContainer } from 'src/common/components/StickyContainer'; import { - StyledDivider, StickyNavItem, StickyNavItemLabel, + StyledDivider, } from 'src/common/components/navigation'; +import { extractStrapiData } from 'src/common/getStrapiData'; +import { hasEnoughCoins } from 'src/common/utils'; +import { CategoryResponse, ServiceResponse } from 'src/features/backoffice'; +import { + useGeti18nCategoriesQuery, + useGeti18nServicesFeaturedQuery, +} from 'src/features/backoffice/strapi'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; +import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; +import i18n from 'src/i18n'; const CategoriesNav = () => { const { t } = useTranslation(); const navigate = useNavigate(); const { status } = useAppSelector((state) => state.user); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const notFoundRoute = useLocalizeRoute('oops'); diff --git a/src/pages/Services/Featured.tsx b/src/pages/Services/Featured.tsx index 6d899339a..a4621e5c1 100644 --- a/src/pages/Services/Featured.tsx +++ b/src/pages/Services/Featured.tsx @@ -1,11 +1,11 @@ import { Paragraph, Row, XXL } from '@appquality/unguess-design-system'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; -import { useAppSelector } from 'src/app/hooks'; import { Divider } from 'src/common/components/divider'; import { extractStrapiData } from 'src/common/getStrapiData'; import { hasEnoughCoins } from 'src/common/utils'; import { useGeti18nServicesFeaturedQuery } from 'src/features/backoffice/strapi'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute'; import i18n from 'src/i18n'; import styled from 'styled-components'; @@ -28,7 +28,7 @@ const FeaturedContainer = styled.div` export const Featured = ({ handleHubspot }: { handleHubspot: () => void }) => { const { t } = useTranslation(); const navigate = useNavigate(); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const notFoundRoute = useLocalizeRoute('oops'); const { diff --git a/src/pages/Services/index.tsx b/src/pages/Services/index.tsx index caf910fe6..d1c6ca6f3 100644 --- a/src/pages/Services/index.tsx +++ b/src/pages/Services/index.tsx @@ -1,20 +1,21 @@ -import { Page } from 'src/features/templates/Page'; -import { useTranslation } from 'react-i18next'; +import { Col, Grid, PageHeader, Row } from '@appquality/unguess-design-system'; import { useMemo, useState } from 'react'; -import styled from 'styled-components'; -import { Col, Grid, Row, PageHeader } from '@appquality/unguess-design-system'; +import { useTranslation } from 'react-i18next'; import { useAppDispatch, useAppSelector } from 'src/app/hooks'; -import { openWizard } from 'src/features/express/expressSlice'; -import PageLoader from 'src/features/templates/PageLoader'; import { HubspotModal } from 'src/common/components/HubspotModal'; +import { LayoutWrapper } from 'src/common/components/LayoutWrapper'; import { PageTitle } from 'src/common/components/PageTitle'; import { checkHubspotURL } from 'src/common/utils'; -import { LayoutWrapper } from 'src/common/components/LayoutWrapper'; -import { Featured } from './Featured'; +import { openWizard } from 'src/features/express/expressSlice'; +import { Page } from 'src/features/templates/Page'; +import PageLoader from 'src/features/templates/PageLoader'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; +import styled from 'styled-components'; +import { ExpressWizardContainer } from '../ExpressWizard'; +import { ExpressDrawer } from '../ExpressWizard/drawer'; import { Categories } from './Categories'; import { CategoriesNav } from './CategoriesNav'; -import { ExpressDrawer } from '../ExpressWizard/drawer'; -import { ExpressWizardContainer } from '../ExpressWizard'; +import { Featured } from './Featured'; const StyledGrid = styled(Grid)` @media screen and (max-width: ${({ theme }) => theme.breakpoints.sm}) { @@ -27,7 +28,7 @@ const Catalog = () => { const dispatch = useAppDispatch(); const [isModalOpen, setIsModalOpen] = useState(false); const { status } = useAppSelector((state) => state.user); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const memoCsm = useMemo(() => activeWorkspace?.csm, [activeWorkspace]); diff --git a/src/pages/Services/services-list/serviceItem.tsx b/src/pages/Services/services-list/serviceItem.tsx index 5ababa845..15df0aa5f 100644 --- a/src/pages/Services/services-list/serviceItem.tsx +++ b/src/pages/Services/services-list/serviceItem.tsx @@ -5,20 +5,21 @@ import { } from '@appquality/unguess-design-system'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; -import i18n from 'src/i18n'; -import { useAppDispatch, useAppSelector } from 'src/app/hooks'; +import { useAppDispatch } from 'src/app/hooks'; +import { ReactComponent as ExperientialIcon } from 'src/assets/icons/experiential-icon.svg'; +import { ReactComponent as ExpressIcon } from 'src/assets/icons/express-icon.svg'; +import { ReactComponent as FunctionalIcon } from 'src/assets/icons/functional-icon.svg'; +import { ReactComponent as TailoredIcon } from 'src/assets/icons/tailored-icon.svg'; import { extractStrapiData } from 'src/common/getStrapiData'; import { hasEnoughCoins, toggleChat } from 'src/common/utils'; import { STRAPI_URL } from 'src/constants'; import { useGetFullServicesByIdQuery } from 'src/features/backoffice/strapi'; -import { ReactComponent as TailoredIcon } from 'src/assets/icons/tailored-icon.svg'; -import { ReactComponent as ExpressIcon } from 'src/assets/icons/express-icon.svg'; -import { ReactComponent as ExperientialIcon } from 'src/assets/icons/experiential-icon.svg'; -import { ReactComponent as FunctionalIcon } from 'src/assets/icons/functional-icon.svg'; import { openDrawer, setExpressTypeId, } from 'src/features/express/expressSlice'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; +import i18n from 'src/i18n'; import { ServiceCol } from './ServiceCol'; export const ServiceItem = ({ @@ -31,7 +32,7 @@ export const ServiceItem = ({ const { t } = useTranslation(); const dispatch = useAppDispatch(); const navigate = useNavigate(); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); const { data, isFetching, isLoading, isError } = useGetFullServicesByIdQuery({ id: serviceId, populate: { diff --git a/src/pages/Services/services-list/serviceTip.tsx b/src/pages/Services/services-list/serviceTip.tsx index 702351d6d..410cdcbad 100644 --- a/src/pages/Services/services-list/serviceTip.tsx +++ b/src/pages/Services/services-list/serviceTip.tsx @@ -1,11 +1,11 @@ import { Button, InfoCard } from '@appquality/unguess-design-system'; import { useTranslation } from 'react-i18next'; -import { useAppSelector } from 'src/app/hooks'; import { ReactComponent as InfoImg } from 'src/assets/icons/info-image.svg'; +import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace'; export const ServiceTip = () => { const { t } = useTranslation(); - const { activeWorkspace } = useAppSelector((state) => state.navigation); + const { activeWorkspace } = useActiveWorkspace(); return (