| @@ -26,6 +26,7 @@ const AppRoutes = () => ( | |||
| /> | |||
| <Route path="api/auth/:provider/callback" element={<AuthCallback />} /> | |||
| <Route element={<RequireAuth />} errorElement={<Error />}> | |||
| <Route path={PAGES.HOME.route} element={<HomePage />} /> | |||
| <Route path={PAGES.BASE.route} element={<HomePage />} /> | |||
| <Route path="/profile/*" element={<ProfilePage />} /> | |||
| <Route path="settings" element={<SettingsPage />} /> | |||
| @@ -3,13 +3,17 @@ import PropTypes from "prop-types"; | |||
| import { HeaderContainer } from "./Header.styled"; | |||
| import { useSelector } from "react-redux"; | |||
| import { selectBreadcrumbs } from "features/app/appSlice"; | |||
| import { selectCurrentUser } from "features/auth/authSlice"; | |||
| import HeaderNavigation from "./HeaderNavigation/HeaderNavigation"; | |||
| const Header = () => { | |||
| const breadcrumbs = useSelector(selectBreadcrumbs); | |||
| console.log(breadcrumbs) | |||
| const user = useSelector(selectCurrentUser); | |||
| console.log(user); | |||
| console.log(breadcrumbs); | |||
| return ( | |||
| <HeaderContainer> | |||
| <div>nesto</div> | |||
| <HeaderNavigation /> | |||
| <div>brate</div> | |||
| </HeaderContainer> | |||
| ); | |||
| @@ -0,0 +1,24 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { headerNavigationConstants } from "constants/navigationConstants"; | |||
| import { HeaderNavigationContainer } from "./HeaderNavigation.styled"; | |||
| import HeaderNavigationItem from "./HeaderNavigationItem/HeaderNavigationItem"; | |||
| const HeaderNavigation = () => { | |||
| return ( | |||
| <HeaderNavigationContainer> | |||
| {headerNavigationConstants.map?.((singleNavigationItem, index) => ( | |||
| <HeaderNavigationItem | |||
| key={index} | |||
| route={singleNavigationItem} | |||
| /> | |||
| ))} | |||
| </HeaderNavigationContainer> | |||
| ); | |||
| }; | |||
| HeaderNavigation.propTypes = { | |||
| children: PropTypes.node, | |||
| }; | |||
| export default HeaderNavigation; | |||
| @@ -6,4 +6,5 @@ export const HeaderNavigationContainer = styled(Box)` | |||
| flex-direction: row; | |||
| align-items: center; | |||
| gap: 16px; | |||
| height: 100%; | |||
| ` | |||
| @@ -1,4 +1,4 @@ | |||
| import React from "react"; | |||
| import React, { useMemo } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| HeaderNavigationItemContainer, | |||
| @@ -7,8 +7,17 @@ import { | |||
| } from "./HeaderNavigationItem.styled"; | |||
| const HeaderNavigationItem = (props) => { | |||
| const singleRoutePath = useMemo(() => { | |||
| const pathArray = props?.route?.route?.split("/"); | |||
| if (pathArray?.[pathArray?.length - 1] === "*") | |||
| pathArray.splice(pathArray?.length - 1, 1); | |||
| return pathArray.join("/"); | |||
| }, [props?.route]); | |||
| return ( | |||
| <HeaderNavigationItemContainer> | |||
| <HeaderNavigationItemContainer | |||
| {...props} | |||
| to={singleRoutePath} | |||
| > | |||
| {props?.route?.icon && ( | |||
| <HeaderNavigationItemIconContainer> | |||
| {props?.route?.icon} | |||
| @@ -26,6 +35,7 @@ HeaderNavigationItem.propTypes = { | |||
| icon: PropTypes.oneOfType([PropTypes.node, PropTypes.element]), | |||
| title: PropTypes.string, | |||
| subroutes: PropTypes.array, | |||
| route: PropTypes.string, | |||
| }), | |||
| }; | |||
| @@ -1,16 +1,30 @@ | |||
| import { Box } from "@mui/material"; | |||
| import { NavLink } from "react-router-dom"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "themes"; | |||
| export const HeaderNavigationItemContainer = styled(Box)` | |||
| export const HeaderNavigationItemContainer = styled(NavLink)` | |||
| display: flex; | |||
| justify-content: center; | |||
| text-decoration: none; | |||
| align-items: center; | |||
| width: fit-content; | |||
| padding: 2px 6px; | |||
| cursor: pointer; | |||
| height: 100%; | |||
| transition-duration: 0.1s; | |||
| &:hover { | |||
| background-color: ${selectedTheme.colors.primaryLightLighter}; | |||
| } | |||
| &[aria-checked=true] ${HeaderNavigationItemIconTitle} { | |||
| font-weight: 700; | |||
| } | |||
| `; | |||
| export const HeaderNavigationItemIconContainer = styled(Box)``; | |||
| export const HeaderNavigationItemIconTitle = styled(Box)` | |||
| font-size: 14px; | |||
| line-height: 20px; | |||
| font-weight: ${(props) => props?.$isActive && 600}; | |||
| color: white; | |||
| font-weight: 500; | |||
| `; | |||
| @@ -0,0 +1,7 @@ | |||
| import { PAGES } from "./pages"; | |||
| export const headerNavigationConstants = [ | |||
| PAGES.HOME, | |||
| PAGES.PROFILE, | |||
| PAGES.SETTINGS, | |||
| ]; | |||
| @@ -51,4 +51,8 @@ export const PAGES = { | |||
| route: "/profile", | |||
| title: i18n.t("pages.profile"), | |||
| }, | |||
| SETTINGS: { | |||
| route: "/settings", | |||
| title: i18n.t("pages.settings"), | |||
| }, | |||
| }; | |||
| @@ -1,4 +1,5 @@ | |||
| import { createSlice } from "@reduxjs/toolkit"; | |||
| import { createSelector } from "reselect"; | |||
| const authSlice = createSlice({ | |||
| name: "auth", | |||
| @@ -19,5 +20,12 @@ const authSlice = createSlice({ | |||
| export const { setCredetnials, logOut } = authSlice.actions; | |||
| export default authSlice.reducer; | |||
| export const selectCurrentUser = (state) => state.auth.user; | |||
| export const selectCurrentToken = (state) => state.auth.token; | |||
| export const authSelector = (state) => state.auth; | |||
| export const selectCurrentUser = createSelector( | |||
| authSelector, | |||
| (state) => state.user | |||
| ); | |||
| export const selectCurrentToken = createSelector( | |||
| authSelector, | |||
| (state) => state.token | |||
| ); | |||
| @@ -52,6 +52,7 @@ export default { | |||
| error: "Pogrešna stranica", | |||
| notFound: "Nije pronađena stranica", | |||
| profile: "Profilna stranica", | |||
| settings: "Podešavanja", | |||
| }, | |||
| register: { | |||
| registerTitle: "Register", | |||
| @@ -1,5 +1,6 @@ | |||
| export const primaryThemeColors = { | |||
| primaryLight: "#673ab7", | |||
| primaryLightLighter: "#845ccb", | |||
| primaryDark: "#009688", | |||
| secondaryLight: "#212121", | |||
| secondaryDark: "#f5f5f5", | |||