diff --git a/frontend/src/components/NavBar.tsx b/frontend/src/components/NavBar.tsx new file mode 100644 index 0000000000..9455a6f219 --- /dev/null +++ b/frontend/src/components/NavBar.tsx @@ -0,0 +1,99 @@ +import { useAppSelector } from '@hooks/useAppSelector' +import { Accent, Icon, IconButton } from '@mtes-mct/monitor-ui' +import ResponsiveNav from '@rsuite/responsive-nav' +import styled from 'styled-components' + +export function NavBar({ children, onClose, onSelect }) { + const currentPath = useAppSelector(state => state.sideWindow.currentPath) + + return ( + } + onItemRemove={onClose} + onSelect={onSelect} + removable + > + {children} + + ) +} + +const StyledResponsiveNav = styled(ResponsiveNav)` + display: flex; + box-shadow: 0px 3px 4px #7077854d; + height: 48px; + width: 100%; + + > .rs-nav-item { + width: 360px; + border-radius: 0px !important; + color: ${p => p.theme.color.slateGray}; + font-size: 14px; + border-right: 1px solid ${p => p.theme.color.lightGray}; + display: flex; + align-items: center; + + &.rs-nav-item-active { + background-color: ${p => p.theme.color.blueGray25}; + color: ${p => p.theme.color.gunMetal}; + font-weight: 500; + border-radius: 0px; + border: 0px !important; + + > .rs-icon { + color: ${p => p.theme.color.slateGray} !important; + } + } + + > span:not(.Element-IconBox) { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + } + + > .rs-icon { + color: ${p => p.theme.color.slateGray}; + } + &:hover { + border-radius: 0px !important; + background-color: ${p => p.theme.color.blueYonder25}; + } + &:first-child { + > svg { + display: none; + } + } + } + > .rs-dropdown { + > .rs-dropdown-toggle { + height: 100%; + border-radius: 0px !important; + > .rs-icon { + display: none; + } + } + > .rs-dropdown-menu { + > .rs-dropdown-item { + color: ${p => p.theme.color.slateGray}; + display: flex; + flex-direction: row; + align-items: center; + &:hover { + background-color: ${p => p.theme.color.blueYonder25}; + } + &.rs-dropdown-item-active { + background-color: ${p => p.theme.color.blueGray25}; + color: ${p => p.theme.color.gunMetal}; + } + } + } + } + > .rs-nav-bar { + border-top: 0px; + } +` diff --git a/frontend/src/domain/entities/sideWindow.ts b/frontend/src/domain/entities/sideWindow.ts index 6a55d19108..52aa203d2f 100644 --- a/frontend/src/domain/entities/sideWindow.ts +++ b/frontend/src/domain/entities/sideWindow.ts @@ -10,6 +10,8 @@ export const sideWindowMenu = { } export const sideWindowPaths = { + DASHBOARD: '/dashboard/:id', + DASHBOARDS: '/dashboards', HOME: '/', MISSION: '/mission/:id', MISSIONS: '/missions', diff --git a/frontend/src/features/Dashboard/components/DashboardMapButton.tsx b/frontend/src/features/Dashboard/components/DashboardMapButton.tsx index b65e346083..6c1354364e 100644 --- a/frontend/src/features/Dashboard/components/DashboardMapButton.tsx +++ b/frontend/src/features/Dashboard/components/DashboardMapButton.tsx @@ -1,8 +1,10 @@ import { DialogButton, DialogSeparator, StyledMapMenuDialogContainer } from '@components/style' import { MenuWithCloseButton } from '@features/commonStyles/map/MenuWithCloseButton' +import { sideWindowActions } from '@features/SideWindow/slice' import { useAppDispatch } from '@hooks/useAppDispatch' import { useAppSelector } from '@hooks/useAppSelector' import { Accent, Button, Icon, MapMenuDialog, Size } from '@mtes-mct/monitor-ui' +import { sideWindowPaths } from 'domain/entities/sideWindow' import { globalActions, setDisplayedItems } from 'domain/shared_slices/Global' import { reduceReportingFormOnMap } from 'domain/use_cases/reporting/reduceReportingFormOnMap' import styled from 'styled-components' @@ -21,6 +23,7 @@ export function DashboardMapButton() { ) dispatch(reduceReportingFormOnMap()) } + const gotToDashboardsList = () => dispatch(sideWindowActions.focusAndGoTo(sideWindowPaths.DASHBOARDS)) return ( <> @@ -35,7 +38,7 @@ export function DashboardMapButton() { Créer un tableau de bord - {}}> + Voir les briefs déjà créés diff --git a/frontend/src/features/Dashboard/components/DashboardsList/index.tsx b/frontend/src/features/Dashboard/components/DashboardsList/index.tsx new file mode 100644 index 0000000000..400d297446 --- /dev/null +++ b/frontend/src/features/Dashboard/components/DashboardsList/index.tsx @@ -0,0 +1,16 @@ +import { SideWindowContent } from '@features/SideWindow/style' +import styled from 'styled-components' + +export function DashboardsList() { + return ( + + Tableaux de bord + + ) +} + +const Title = styled.h1` + color: ${p => p.theme.color.gunMetal}; + font-size: 22px; + line-height: 50px; +` diff --git a/frontend/src/features/Dashboard/components/DashboardsNavBar.tsx b/frontend/src/features/Dashboard/components/DashboardsNavBar.tsx new file mode 100644 index 0000000000..9453626b2d --- /dev/null +++ b/frontend/src/features/Dashboard/components/DashboardsNavBar.tsx @@ -0,0 +1,44 @@ +import { NavBar } from '@components/NavBar' +import { Icon, THEME } from '@mtes-mct/monitor-ui' +import ResponsiveNav from '@rsuite/responsive-nav' +import { sideWindowPaths } from 'domain/entities/sideWindow' +import { useMemo } from 'react' +import { generatePath } from 'react-router' + +export function DashboardsNavBar() { + const tabs = useMemo(() => { + const dashboardsList = { + icon: , + label: 'Liste des tableaux de bords', + nextPath: sideWindowPaths.DASHBOARDS + } + + // TODO 19/09 : replace with real data + const openDashboards = { + icon: , + label: Tab XX/XX/XX, + nextPath: generatePath(sideWindowPaths.MISSION, { id: 1 }) + } + + return [dashboardsList, openDashboards] + }, []) + + const selectDashboard = () => {} + + const closeDashboard = () => {} + + return ( + + {tabs.map((item, index) => ( + + {item.label} + + ))} + + ) +} diff --git a/frontend/src/features/Reportings/components/ReportingsList/index.tsx b/frontend/src/features/Reportings/components/ReportingsList/index.tsx index 54b2323aa9..48914222c6 100644 --- a/frontend/src/features/Reportings/components/ReportingsList/index.tsx +++ b/frontend/src/features/Reportings/components/ReportingsList/index.tsx @@ -1,5 +1,6 @@ import { ReportingsFilters } from '@features/Reportings/Filters' import { useGetFilteredReportingsQuery } from '@features/Reportings/hooks/useGetFilteredReportingsQuery' +import { SideWindowContent } from '@features/SideWindow/style' import { useAppDispatch } from '@hooks/useAppDispatch' import { useGetControlPlans } from '@hooks/useGetControlPlans' import { Button, Icon } from '@mtes-mct/monitor-ui' @@ -20,7 +21,7 @@ export function ReportingsList() { } return ( - + Signalements @@ -34,18 +35,10 @@ export function ReportingsList() { ) : ( )} - + ) } -const StyledReportingsContainer = styled.div` - display: flex; - flex: 1; - flex-direction: column; - padding: 40px; - overflow: auto; -` - const StyledHeader = styled.div` display: flex; flex-direction: row; diff --git a/frontend/src/features/SideWindow/index.tsx b/frontend/src/features/SideWindow/index.tsx index 11c3372be5..e1212b1963 100644 --- a/frontend/src/features/SideWindow/index.tsx +++ b/frontend/src/features/SideWindow/index.tsx @@ -1,3 +1,5 @@ +import { DashboardsList } from '@features/Dashboard/components/DashboardsList' +import { DashboardsNavBar } from '@features/Dashboard/components/DashboardsNavBar' import { REPORTING_EVENT_UNSYNCHRONIZED_PROPERTIES } from '@features/Reportings/components/ReportingForm/constants' import { useListenReportingEventUpdates } from '@features/Reportings/components/ReportingForm/hooks/useListenReportingEventUpdates' import { ReportingsList } from '@features/Reportings/components/ReportingsList' @@ -18,7 +20,7 @@ import { ReportingContext } from '../../domain/shared_slices/Global' import { switchTab } from '../../domain/use_cases/missions/switchTab' import { useAppDispatch } from '../../hooks/useAppDispatch' import { useAppSelector } from '../../hooks/useAppSelector' -import { isMissionOrMissionsPage, isMissionPage, isReportingsPage } from '../../utils/routes' +import { isDashboardsPage, isMissionOrMissionsPage, isMissionPage, isReportingsPage } from '../../utils/routes' import { MissionFormWrapper } from '../missions/MissionForm' import { MISSION_EVENT_UNSYNCHRONIZED_PROPERTIES } from '../missions/MissionForm/constants' import { useListenMissionEventUpdates } from '../missions/MissionForm/hooks/useListenMissionEventUpdates' @@ -37,6 +39,7 @@ export function SideWindow() { const isMissionButtonIsActive = useMemo(() => isMissionOrMissionsPage(currentPath), [currentPath]) const isReportingsButtonIsActive = useMemo(() => isReportingsPage(currentPath), [currentPath]) + const isDashboardsButtonIsActive = useMemo(() => isDashboardsPage(currentPath), [currentPath]) /** * Use to update mission opened in the side window but not actives @@ -106,6 +109,12 @@ export function SideWindow() { onClick={() => navigate(generatePath(sideWindowPaths.REPORTINGS))} title="Signalements" /> + navigate(generatePath(sideWindowPaths.DASHBOARDS))} + title="Tableaux de bord" + /> @@ -113,6 +122,11 @@ export function SideWindow() { } path={[sideWindowPaths.MISSIONS, sideWindowPaths.MISSION]} /> } path={sideWindowPaths.MISSIONS} /> } path={sideWindowPaths.MISSION} /> + } + path={[sideWindowPaths.DASHBOARDS, sideWindowPaths.DASHBOARD]} + /> + } path={sideWindowPaths.DASHBOARDS} /> {isReportingsButtonIsActive && ( diff --git a/frontend/src/features/SideWindow/style.ts b/frontend/src/features/SideWindow/style.ts index 5fc656d7e3..aa1cb717c8 100644 --- a/frontend/src/features/SideWindow/style.ts +++ b/frontend/src/features/SideWindow/style.ts @@ -26,3 +26,11 @@ export const StyledRouteContainer = styled.section` flex-direction: column; width: calc(100vw - 64px); ` + +export const SideWindowContent = styled.div` + display: flex; + flex: 1; + flex-direction: column; + padding: 40px; + overflow: auto; +` diff --git a/frontend/src/features/missions/MissionsList/index.tsx b/frontend/src/features/missions/MissionsList/index.tsx index 939df2d205..d9d6b265ad 100644 --- a/frontend/src/features/missions/MissionsList/index.tsx +++ b/frontend/src/features/missions/MissionsList/index.tsx @@ -1,3 +1,4 @@ +import { SideWindowContent } from '@features/SideWindow/style' import { Button, Icon } from '@mtes-mct/monitor-ui' import styled from 'styled-components' @@ -17,7 +18,7 @@ export function Missions() { } return ( - + Missions et contrôles @@ -34,18 +35,10 @@ export function Missions() { ) : ( )} - + ) } -const StyledMissionsContainer = styled.div` - display: flex; - flex: 1; - flex-direction: column; - padding: 40px; - overflow: auto; -` - const StyledHeader = styled.div` display: flex; flex-direction: row; diff --git a/frontend/src/features/missions/MissionsNavBar.tsx b/frontend/src/features/missions/MissionsNavBar.tsx index 0bb21bf0c1..b23a6a86f7 100644 --- a/frontend/src/features/missions/MissionsNavBar.tsx +++ b/frontend/src/features/missions/MissionsNavBar.tsx @@ -1,4 +1,5 @@ -import { Accent, Icon, IconButton } from '@mtes-mct/monitor-ui' +import { NavBar } from '@components/NavBar' +import { Icon } from '@mtes-mct/monitor-ui' import ResponsiveNav from '@rsuite/responsive-nav' import { useMemo } from 'react' import { generatePath } from 'react-router-dom' @@ -24,7 +25,6 @@ function MissionStatus({ mission }) { } export function MissionsNavBar() { - const currentPath = useAppSelector(state => state.sideWindow.currentPath) const selectedMissions = useAppSelector(state => state.missionForms.missions) const dispatch = useAppDispatch() @@ -65,101 +65,16 @@ export function MissionsNavBar() { } return ( - } - onItemRemove={removeTab} - onSelect={selectTab} - removable - > + {tabs.map((item, index) => ( {item.label} ))} - + ) } -const StyledResponsiveNav = styled(ResponsiveNav)` - display: flex; - box-shadow: 0px 3px 4px #7077854d; - height: 48px; - width: 100%; - - > .rs-nav-item { - width: 360px; - border-radius: 0px !important; - color: ${p => p.theme.color.slateGray}; - font-size: 14px; - border-right: 1px solid ${p => p.theme.color.lightGray}; - display: flex; - align-items: center; - - &.rs-nav-item-active { - background-color: ${p => p.theme.color.blueGray25}; - color: ${p => p.theme.color.gunMetal}; - font-weight: 500; - border-radius: 0px; - border: 0px !important; - - > .rs-icon { - color: ${p => p.theme.color.slateGray} !important; - } - } - - > span:not(.Element-IconBox) { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - width: 100%; - } - - > .rs-icon { - color: ${p => p.theme.color.slateGray}; - } - &:hover { - border-radius: 0px !important; - background-color: ${p => p.theme.color.blueYonder25}; - } - &:first-child { - > svg { - display: none; - } - } - } - > .rs-dropdown { - > .rs-dropdown-toggle { - height: 100%; - border-radius: 0px !important; - > .rs-icon { - display: none; - } - } - > .rs-dropdown-menu { - > .rs-dropdown-item { - color: ${p => p.theme.color.slateGray}; - display: flex; - flex-direction: row; - align-items: center; - &:hover { - background-color: ${p => p.theme.color.blueYonder25}; - } - &.rs-dropdown-item-active { - background-color: ${p => p.theme.color.blueGray25}; - color: ${p => p.theme.color.gunMetal}; - } - } - } - } - > .rs-nav-bar { - border-top: 0px; - } -` - export const StyledStatus = styled.div<{ borderColor: string | undefined; color: string }>` height: 12px; width: 12px; diff --git a/frontend/src/utils/routes.ts b/frontend/src/utils/routes.ts index 57a0b2db7e..4e0b0b8a3a 100644 --- a/frontend/src/utils/routes.ts +++ b/frontend/src/utils/routes.ts @@ -42,3 +42,13 @@ export function isReportingsPage(path: string) { path as string ) } + +export function isDashboardsPage(path: string) { + return !!matchPath( + { + end: true, + path: sideWindowPaths.DASHBOARDS + }, + path as string + ) +}